--- /dev/null
+---
+Language: Cpp
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignArrayOfStructures: None
+AlignConsecutiveAssignments:
+ Enabled: true
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ PadOperators: true
+AlignConsecutiveBitFields:
+ Enabled: true
+ AcrossEmptyLines: true
+ AcrossComments: false
+ AlignCompound: false
+ PadOperators: false
+AlignConsecutiveDeclarations:
+ Enabled: true
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ PadOperators: false
+AlignConsecutiveMacros:
+ Enabled: true
+ AcrossEmptyLines: true
+ AcrossComments: false
+ AlignCompound: false
+ PadOperators: false
+AlignEscapedNewlines: Right
+AlignOperands: Align
+AlignTrailingComments:
+ Kind: Always
+ OverEmptyLines: 0
+AllowAllArgumentsOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortEnumsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLambdasOnASingleLine: All
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: MultiLine
+AttributeMacros:
+ - __capability
+BinPackArguments: true
+BinPackParameters: true
+BitFieldColonSpacing: Both
+BraceWrapping:
+ AfterCaseLabel: false
+ AfterClass: false
+ AfterControlStatement: Never
+ AfterEnum: false
+ AfterExternBlock: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ BeforeLambdaBody: false
+ BeforeWhile: false
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakAfterAttributes: Never
+BreakAfterJavaFieldAnnotations: false
+BreakArrays: true
+BreakBeforeBinaryOperators: None
+BreakBeforeConceptDeclarations: Always
+BreakBeforeBraces: Attach
+BreakBeforeInlineASMColon: OnlyMultiline
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: BeforeColon
+BreakInheritanceList: BeforeColon
+BreakStringLiterals: true
+ColumnLimit: 120
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat: false
+EmptyLineAfterAccessModifier: Never
+EmptyLineBeforeAccessModifier: LogicalBlock
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IfMacros:
+ - KJ_IF_MAYBE
+IncludeBlocks: Preserve
+IncludeCategories:
+ - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ Priority: 2
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '^(<|"(gtest|gmock|isl|json)/)'
+ Priority: 3
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '.*'
+ Priority: 1
+ SortPriority: 0
+ CaseSensitive: false
+IncludeIsMainRegex: '(Test)?$'
+IncludeIsMainSourceRegex: ''
+IndentAccessModifiers: false
+IndentCaseBlocks: false
+IndentCaseLabels: false
+IndentExternBlock: AfterExternBlock
+IndentGotoLabels: true
+IndentPPDirectives: None
+IndentRequiresClause: true
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+InsertBraces: false
+InsertNewlineAtEOF: false
+InsertTrailingCommas: None
+IntegerLiteralSeparator:
+ Binary: 0
+ BinaryMinDigits: 0
+ Decimal: 0
+ DecimalMinDigits: 0
+ Hex: 0
+ HexMinDigits: 0
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+LambdaBodyIndentation: Signature
+LineEnding: DeriveLF
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 2
+ObjCBreakBeforeNestedBlockParam: true
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PackConstructorInitializers: BinPack
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakOpenParenthesis: 0
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyIndentedWhitespace: 0
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Right
+PPIndentWidth: -1
+QualifierAlignment: Leave
+ReferenceAlignment: Pointer
+ReflowComments: true
+RemoveBracesLLVM: false
+RemoveSemicolon: false
+RequiresClausePosition: OwnLine
+RequiresExpressionIndentation: OuterScope
+SeparateDefinitionBlocks: Leave
+ShortNamespaceLines: 1
+SortIncludes: false
+SortJavaStaticImport: Before
+SortUsingDeclarations: LexicographicNumeric
+SpaceAfterCStyleCast: false
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: true
+SpaceAroundPointerQualifiers: Default
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCaseColon: false
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeParensOptions:
+ AfterControlStatements: true
+ AfterForeachMacros: true
+ AfterFunctionDefinitionName: false
+ AfterFunctionDeclarationName: false
+ AfterIfMacros: true
+ AfterOverloadedOperator: false
+ AfterRequiresInClause: false
+ AfterRequiresInExpression: false
+ BeforeNonEmptyParentheses: false
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceBeforeSquareBrackets: false
+SpaceInEmptyBlock: false
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: Never
+SpacesInConditionalStatement: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInLineCommentPrefix:
+ Minimum: 1
+ Maximum: -1
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Latest
+StatementAttributeLikeMacros:
+ - Q_EMIT
+StatementMacros:
+ - Q_UNUSED
+ - QT_REQUIRE_VERSION
+TabWidth: 4
+UseTab: Never
+WhitespaceSensitiveMacros:
+ - BOOST_PP_STRINGIZE
+ - CF_SWIFT_NAME
+ - NS_SWIFT_NAME
+ - PP_STRINGIZE
+ - STRINGIZE
+...
+
#endif
#ifdef VKVG_SVG
-typedef struct _vkvg_svg_t* VkvgSvg;
+typedef struct _vkvg_svg_t *VkvgSvg;
#else
-typedef struct NSVGimage* VkvgSvg;
+typedef struct NSVGimage *VkvgSvg;
#endif
/**
* @brief load svg file into @ref surface
* @param height force the rendering height, if 0 autosize from svg.
* @return The new vkvg surface with the loaded SVG drawing as content, or null if an error occured.
*/
-vkvg_public
-VkvgSurface vkvg_surface_create_from_svg(VkvgDevice dev, uint32_t width, uint32_t height, const char* svgFilePath);
+vkvg_public VkvgSurface vkvg_surface_create_from_svg(VkvgDevice dev, uint32_t width, uint32_t height,
+ const char *svgFilePath);
/**
* @brief create surface from svg fragment
*
* @param svgFragment The SVG fragment to parse.
* @return The new vkvg surface with the parsed SVG fragment as content, or null if an error occured.
*/
-vkvg_public
-VkvgSurface vkvg_surface_create_from_svg_fragment(VkvgDevice dev, uint32_t width, uint32_t height, char* svgFragment);
+vkvg_public VkvgSurface vkvg_surface_create_from_svg_fragment(VkvgDevice dev, uint32_t width, uint32_t height,
+ char *svgFragment);
/**
* @brief get svg dimensions.
*
* @param width pointer to a valid integer to receive the svg width.
* @param height pointer to a valid integer to receive the svg height.
*/
-vkvg_public
-void vkvg_svg_get_dimensions (VkvgSvg svg, uint32_t* width, uint32_t* height);
+vkvg_public void vkvg_svg_get_dimensions(VkvgSvg svg, uint32_t *width, uint32_t *height);
/**
* @brief Load svg file in memory.
* @param svgFilePath a valid file path to the svg to load.
* @return a VkvgSvg pointer.
*/
-vkvg_public
-VkvgSvg vkvg_svg_load (const char* svgFilePath);
+vkvg_public VkvgSvg vkvg_svg_load(const char *svgFilePath);
/**
* @brief Load svg from an svg source fragment.
* @param svgFragment A valid svg code fragment.
* @return a VkvgSvg pointer.
*/
-vkvg_public
-VkvgSvg vkvg_svg_load_fragment (char* svgFragment);
+vkvg_public VkvgSvg vkvg_svg_load_fragment(char *svgFragment);
/**
* @brief render svg on a context.
* @param ctx a valid vkvg context.
* @param id an optional id to limit rendering to specific `<g>` elemnt.
*/
-vkvg_public
-void vkvg_svg_render (VkvgSvg svg, VkvgContext ctx, const char* id);
+vkvg_public void vkvg_svg_render(VkvgSvg svg, VkvgContext ctx, const char *id);
/**
* @brief release VkvgSvg pointer resources.
* @param svg a valid VkvgSvg handle to free.
*/
-vkvg_public
-void vkvg_svg_destroy (VkvgSvg svg);
+vkvg_public void vkvg_svg_destroy(VkvgSvg svg);
#ifdef __cplusplus
}
/** @mainpage Documentation
*
- * VKVG is an open source 2d vector drawing library written in @b c and using [vulkan](https://www.khronos.org/vulkan/) for hardware acceleration.
+ * VKVG is an open source 2d vector drawing library written in @b c and using [vulkan](https://www.khronos.org/vulkan/)
+ * for hardware acceleration.
*
* @image html screenshot3.png
*
- * Its api is modeled on the [cairo graphic library](https://www.cairographics.org/) with the following software components:
+ * Its api is modeled on the [cairo graphic library](https://www.cairographics.org/) with the following software
+ * components:
*
* - @ref surface
* - @ref context
#include <stdbool.h>
#ifndef vkvg_public
- #ifdef VKVG_SHARED_BUILD
- #if (defined(_WIN32) || defined(_WIN64))
- #define vkvg_public __declspec(dllexport)
- #else
- #define vkvg_public __attribute__((visibility("default")))
- #endif
- #elif (defined(VKVG_SHARED_LINKING) && (defined(_WIN32) || defined(_WIN64)))
- #define vkvg_public __declspec(dllimport)
- #else
- #define vkvg_public
- #endif
+#ifdef VKVG_SHARED_BUILD
+#if (defined(_WIN32) || defined(_WIN64))
+#define vkvg_public __declspec(dllexport)
+#else
+#define vkvg_public __attribute__((visibility("default")))
+#endif
+#elif (defined(VKVG_SHARED_LINKING) && (defined(_WIN32) || defined(_WIN64)))
+#define vkvg_public __declspec(dllimport)
+#else
+#define vkvg_public
+#endif
#endif
+#define VKVG_LOG_ERR 0x00000001
+#define VKVG_LOG_DEBUG 0x00000002
-#define VKVG_LOG_ERR 0x00000001
-#define VKVG_LOG_DEBUG 0x00000002
-
-#define VKVG_LOG_INFO_PTS 0x00000004
-#define VKVG_LOG_INFO_PATH 0x00000008
-#define VKVG_LOG_INFO_CMD 0x00000010
-#define VKVG_LOG_INFO_VBO 0x00000020
-#define VKVG_LOG_INFO_IBO 0x00000040
-#define VKVG_LOG_INFO_VAO (VKVG_LOG_INFO_VBO|VKVG_LOG_INFO_IBO)
-#define VKVG_LOG_THREAD 0x00000080
-#define VKVG_LOG_DBG_ARRAYS 0x00001000
-#define VKVG_LOG_STROKE 0x00010000
-#define VKVG_LOG_FULL 0xffffffff
+#define VKVG_LOG_INFO_PTS 0x00000004
+#define VKVG_LOG_INFO_PATH 0x00000008
+#define VKVG_LOG_INFO_CMD 0x00000010
+#define VKVG_LOG_INFO_VBO 0x00000020
+#define VKVG_LOG_INFO_IBO 0x00000040
+#define VKVG_LOG_INFO_VAO (VKVG_LOG_INFO_VBO | VKVG_LOG_INFO_IBO)
+#define VKVG_LOG_THREAD 0x00000080
+#define VKVG_LOG_DBG_ARRAYS 0x00001000
+#define VKVG_LOG_STROKE 0x00010000
+#define VKVG_LOG_FULL 0xffffffff
-#define VKVG_LOG_INFO 0x00008000//(VKVG_LOG_INFO_PTS|VKVG_LOG_INFO_PATH|VKVG_LOG_INFO_CMD|VKVG_LOG_INFO_VAO)
+#define VKVG_LOG_INFO 0x00008000 //(VKVG_LOG_INFO_PTS|VKVG_LOG_INFO_PATH|VKVG_LOG_INFO_CMD|VKVG_LOG_INFO_VAO)
#ifdef DEBUG
- extern uint32_t vkvg_log_level;
- #ifdef VKVG_WIRED_DEBUG
- typedef enum {
- vkvg_wired_debug_mode_normal = 0x01,
- vkvg_wired_debug_mode_points = 0x02,
- vkvg_wired_debug_mode_lines = 0x04,
- vkvg_wired_debug_mode_both = vkvg_wired_debug_mode_points|vkvg_wired_debug_mode_lines,
- vkvg_wired_debug_mode_all = 0xFFFFFFFF
- }vkvg_wired_debug_mode;
- extern vkvg_wired_debug_mode vkvg_wired_debug;
- #endif
+extern uint32_t vkvg_log_level;
+#ifdef VKVG_WIRED_DEBUG
+typedef enum {
+ vkvg_wired_debug_mode_normal = 0x01,
+ vkvg_wired_debug_mode_points = 0x02,
+ vkvg_wired_debug_mode_lines = 0x04,
+ vkvg_wired_debug_mode_both = vkvg_wired_debug_mode_points | vkvg_wired_debug_mode_lines,
+ vkvg_wired_debug_mode_all = 0xFFFFFFFF
+} vkvg_wired_debug_mode;
+extern vkvg_wired_debug_mode vkvg_wired_debug;
+#endif
#endif
/**
* As soon as a status is not success, further operations will be canceled.
*/
typedef enum {
- VKVG_STATUS_SUCCESS = 0, /*!< no error occurred.*/
- VKVG_STATUS_NO_MEMORY, /*!< out of memory*/
- VKVG_STATUS_INVALID_RESTORE, /*!< call to #vkvg_restore without matching call to #vkvg_save*/
- VKVG_STATUS_NO_CURRENT_POINT, /*!< path command expecting a current point to be defined failed*/
- VKVG_STATUS_INVALID_MATRIX, /*!< invalid matrix (not invertible)*/
- VKVG_STATUS_INVALID_STATUS, /*!< */
- VKVG_STATUS_INVALID_INDEX, /*!< */
- VKVG_STATUS_NULL_POINTER, /*!< NULL pointer*/
- VKVG_STATUS_WRITE_ERROR, /*!< */
- VKVG_STATUS_PATTERN_TYPE_MISMATCH, /*!< */
- VKVG_STATUS_PATTERN_INVALID_GRADIENT,/*!< occurs when stops count is zero */
- VKVG_STATUS_INVALID_FORMAT, /*!< */
- VKVG_STATUS_FILE_NOT_FOUND, /*!< */
- VKVG_STATUS_INVALID_DASH, /*!< invalid value for a dash setting */
- VKVG_STATUS_INVALID_RECT, /*!< rectangle with height or width equal to 0. */
- VKVG_STATUS_TIMEOUT, /*!< waiting for a vulkan operation to finish resulted in a fence timeout (5 seconds)*/
- VKVG_STATUS_DEVICE_ERROR, /*!< vkvg device initialization error */
- VKVG_STATUS_INVALID_IMAGE, /*!< */
- VKVG_STATUS_INVALID_SURFACE, /*!< */
- VKVG_STATUS_INVALID_FONT, /*!< Unresolved font name*/
- VKVG_STATUS_ENUM_MAX = 0x7FFFFFFF
-}vkvg_status_t;
+ VKVG_STATUS_SUCCESS = 0, /*!< no error occurred.*/
+ VKVG_STATUS_NO_MEMORY, /*!< out of memory*/
+ VKVG_STATUS_INVALID_RESTORE, /*!< call to #vkvg_restore without matching call to #vkvg_save*/
+ VKVG_STATUS_NO_CURRENT_POINT, /*!< path command expecting a current point to be defined failed*/
+ VKVG_STATUS_INVALID_MATRIX, /*!< invalid matrix (not invertible)*/
+ VKVG_STATUS_INVALID_STATUS, /*!< */
+ VKVG_STATUS_INVALID_INDEX, /*!< */
+ VKVG_STATUS_NULL_POINTER, /*!< NULL pointer*/
+ VKVG_STATUS_WRITE_ERROR, /*!< */
+ VKVG_STATUS_PATTERN_TYPE_MISMATCH, /*!< */
+ VKVG_STATUS_PATTERN_INVALID_GRADIENT, /*!< occurs when stops count is zero */
+ VKVG_STATUS_INVALID_FORMAT, /*!< */
+ VKVG_STATUS_FILE_NOT_FOUND, /*!< */
+ VKVG_STATUS_INVALID_DASH, /*!< invalid value for a dash setting */
+ VKVG_STATUS_INVALID_RECT, /*!< rectangle with height or width equal to 0. */
+ VKVG_STATUS_TIMEOUT, /*!< waiting for a vulkan operation to finish resulted in a fence timeout (5 seconds)*/
+ VKVG_STATUS_DEVICE_ERROR, /*!< vkvg device initialization error */
+ VKVG_STATUS_INVALID_IMAGE, /*!< */
+ VKVG_STATUS_INVALID_SURFACE, /*!< */
+ VKVG_STATUS_INVALID_FONT, /*!< Unresolved font name*/
+ VKVG_STATUS_ENUM_MAX = 0x7FFFFFFF
+} vkvg_status_t;
-typedef enum {
- VKVG_HORIZONTAL = 0,
- VKVG_VERTICAL = 1
-}vkvg_direction_t;
+typedef enum { VKVG_HORIZONTAL = 0, VKVG_VERTICAL = 1 } vkvg_direction_t;
-typedef enum {
- VKVG_FORMAT_ARGB32,
- VKVG_FORMAT_RGB24,
- VKVG_FORMAT_A8,
- VKVG_FORMAT_A1
-} vkvg_format_t;
+typedef enum { VKVG_FORMAT_ARGB32, VKVG_FORMAT_RGB24, VKVG_FORMAT_A8, VKVG_FORMAT_A1 } vkvg_format_t;
/**
* @brief pattern border policy
*
* the extend defines how the pattern will be rendered outside its original bounds.
*/
typedef enum {
- VKVG_EXTEND_NONE, /*!< nothing will be outputed outside the pattern original bounds */
- VKVG_EXTEND_REPEAT, /*!< pattern will be repeated to fill all the target bounds */
- VKVG_EXTEND_REFLECT, /*!< pattern will be repeated but mirrored on each repeat */
- VKVG_EXTEND_PAD /*!< the last pixels making the borders of the pattern will be extended to the whole target */
+ VKVG_EXTEND_NONE, /*!< nothing will be outputed outside the pattern original bounds */
+ VKVG_EXTEND_REPEAT, /*!< pattern will be repeated to fill all the target bounds */
+ VKVG_EXTEND_REFLECT, /*!< pattern will be repeated but mirrored on each repeat */
+ VKVG_EXTEND_PAD /*!< the last pixels making the borders of the pattern will be extended to the whole target */
} vkvg_extend_t;
-
typedef enum {
- VKVG_FILTER_FAST,
- VKVG_FILTER_GOOD,
- VKVG_FILTER_BEST,
- VKVG_FILTER_NEAREST,
- VKVG_FILTER_BILINEAR,
- VKVG_FILTER_GAUSSIAN,
+ VKVG_FILTER_FAST,
+ VKVG_FILTER_GOOD,
+ VKVG_FILTER_BEST,
+ VKVG_FILTER_NEAREST,
+ VKVG_FILTER_BILINEAR,
+ VKVG_FILTER_GAUSSIAN,
} vkvg_filter_t;
/**
*
*/
typedef enum {
- VKVG_PATTERN_TYPE_SOLID, /*!< single color pattern */
- VKVG_PATTERN_TYPE_SURFACE, /*!< vkvg surface pattern */
- VKVG_PATTERN_TYPE_LINEAR, /*!< linear gradient pattern */
- VKVG_PATTERN_TYPE_RADIAL, /*!< radial gradient pattern */
- VKVG_PATTERN_TYPE_MESH, /*!< not implemented */
- VKVG_PATTERN_TYPE_RASTER_SOURCE, /*!< not implemented */
+ VKVG_PATTERN_TYPE_SOLID, /*!< single color pattern */
+ VKVG_PATTERN_TYPE_SURFACE, /*!< vkvg surface pattern */
+ VKVG_PATTERN_TYPE_LINEAR, /*!< linear gradient pattern */
+ VKVG_PATTERN_TYPE_RADIAL, /*!< radial gradient pattern */
+ VKVG_PATTERN_TYPE_MESH, /*!< not implemented */
+ VKVG_PATTERN_TYPE_RASTER_SOURCE, /*!< not implemented */
} vkvg_pattern_type_t;
/**
* configuration which may be accessed with #vkvg_set_line_cap and #vkvg_get_line_cap
*/
typedef enum {
- VKVG_LINE_CAP_BUTT, /*!< normal line endings, this is the default. */
- VKVG_LINE_CAP_ROUND, /*!< rounded line caps */
- VKVG_LINE_CAP_SQUARE /*!< extend the caps with squared terminations having border equal to current line width. */
+ VKVG_LINE_CAP_BUTT, /*!< normal line endings, this is the default. */
+ VKVG_LINE_CAP_ROUND, /*!< rounded line caps */
+ VKVG_LINE_CAP_SQUARE /*!< extend the caps with squared terminations having border equal to current line width. */
} vkvg_line_cap_t;
/**
* @brief lines articulations
* in the context and may be accessed with #vkvg_set_line_join and #vkvg_get_line_join.
*/
typedef enum {
- VKVG_LINE_JOIN_MITER, /*!< normal joins with sharp angles, this is the default. */
- VKVG_LINE_JOIN_ROUND, /*!< joins are rounded on the exterior border of the line. */
- VKVG_LINE_JOIN_BEVEL /*!< beveled line joins. */
+ VKVG_LINE_JOIN_MITER, /*!< normal joins with sharp angles, this is the default. */
+ VKVG_LINE_JOIN_ROUND, /*!< joins are rounded on the exterior border of the line. */
+ VKVG_LINE_JOIN_BEVEL /*!< beveled line joins. */
} vkvg_line_join_t;
/**
* All further drawing and clipping operations are affected by this setting.
*/
typedef enum {
- VKVG_FILL_RULE_EVEN_ODD, /*!< even-odd fill rule */
- VKVG_FILL_RULE_NON_ZERO /*!< non zero fill rule */
+ VKVG_FILL_RULE_EVEN_ODD, /*!< even-odd fill rule */
+ VKVG_FILL_RULE_NON_ZERO /*!< non zero fill rule */
} vkvg_fill_rule_t;
typedef struct {
- float r; /*!< the red component */
- float g; /*!< the green component */
- float b; /*!< the blue component */
- float a; /*!< the alpha component */
+ float r; /*!< the red component */
+ float g; /*!< the green component */
+ float b; /*!< the blue component */
+ float a; /*!< the alpha component */
} vkvg_color_t;
/**
- * @brief font metrics
- *
- * structure defining global font metrics for a particular font. It can be retrieve by calling @ref vkvg_font_extents
- * on a valid context.
- */
+ * @brief font metrics
+ *
+ * structure defining global font metrics for a particular font. It can be retrieve by calling @ref vkvg_font_extents
+ * on a valid context.
+ */
typedef struct {
- float ascent; /*!< the distance that the font extends above the baseline. */
- float descent; /*!< the distance that the font extends below the baseline.*/
- float height; /*!< the recommended vertical distance between baselines. */
- float max_x_advance; /*!< the maximum distance in the X direction that the origin is advanced for any glyph in the font.*/
- float max_y_advance; /*!< the maximum distance in the Y direction that the origin is advanced for any glyph in the font. This will be zero for normal fonts used for horizontal writing.*/
+ float ascent; /*!< the distance that the font extends above the baseline. */
+ float descent; /*!< the distance that the font extends below the baseline.*/
+ float height; /*!< the recommended vertical distance between baselines. */
+ float max_x_advance; /*!< the maximum distance in the X direction that the origin is advanced for any glyph in the
+ font.*/
+ float max_y_advance; /*!< the maximum distance in the Y direction that the origin is advanced for any glyph in the
+ font. This will be zero for normal fonts used for horizontal writing.*/
} vkvg_font_extents_t;
/**
- * @brief text metrics
- *
- * structure defining metrics for a single or a string of glyphs. To measure text, call @ref vkvg_text_extents
- * on a valid context.
- */
+ * @brief text metrics
+ *
+ * structure defining metrics for a single or a string of glyphs. To measure text, call @ref vkvg_text_extents
+ * on a valid context.
+ */
typedef struct {
- float x_bearing; /*!< the horizontal distance from the origin to the leftmost part of the glyphs as drawn. Positive if the glyphs lie entirely to the right of the origin. */
- float y_bearing; /*!< the vertical distance from the origin to the topmost part of the glyphs as drawn. Positive only if the glyphs lie completely below the origin; will usually be negative.*/
- float width; /*!< width of the glyphs as drawn*/
- float height; /*!< height of the glyphs as drawn*/
- float x_advance; /*!< distance to advance in the X direction after drawing these glyphs*/
- float y_advance; /*!< distance to advance in the Y direction after drawing these glyphs. Will typically be zero except for vertical text layout as found in East-Asian languages.*/
+ float x_bearing; /*!< the horizontal distance from the origin to the leftmost part of the glyphs as drawn. Positive
+ if the glyphs lie entirely to the right of the origin. */
+ float y_bearing; /*!< the vertical distance from the origin to the topmost part of the glyphs as drawn. Positive
+ only if the glyphs lie completely below the origin; will usually be negative.*/
+ float width; /*!< width of the glyphs as drawn*/
+ float height; /*!< height of the glyphs as drawn*/
+ float x_advance; /*!< distance to advance in the X direction after drawing these glyphs*/
+ float y_advance; /*!< distance to advance in the Y direction after drawing these glyphs. Will typically be zero
+ except for vertical text layout as found in East-Asian languages.*/
} vkvg_text_extents_t;
/**
- * @brief glyphs position in a @ref VkvgText
- *
- * structure defining glyph position as computed for rendering a text run.
- * the codepoint field is for internal use only.
- */
+ * @brief glyphs position in a @ref VkvgText
+ *
+ * structure defining glyph position as computed for rendering a text run.
+ * the codepoint field is for internal use only.
+ */
typedef struct _glyph_info_t {
- int32_t x_advance;
- int32_t y_advance;
- int32_t x_offset;
- int32_t y_offset;
- /* private */
- uint32_t codepoint;//should be named glyphIndex, but for harfbuzz compatibility...
+ int32_t x_advance;
+ int32_t y_advance;
+ int32_t x_offset;
+ int32_t y_offset;
+ /* private */
+ uint32_t codepoint; // should be named glyphIndex, but for harfbuzz compatibility...
} vkvg_glyph_info_t;
/**
* Drawing text with @ref vkvg_show_text() implicitly create such intermediate structure
* that is destroyed imediatly after the function call.
*/
-typedef struct _vkvg_text_run_t* VkvgText;
+typedef struct _vkvg_text_run_t *VkvgText;
/**
* @brief The Vkvg drawing Context.
*
* A #VkvgContext is the central object for drawing operations.
*/
-typedef struct _vkvg_context_t* VkvgContext;
+typedef struct _vkvg_context_t *VkvgContext;
/**
* @brief Opaque pointer on a Vkvg Surface structure.
* @ingroup surface
* with the surface as the target, using #vkvg_create().
*
*/
-typedef struct _vkvg_surface_t* VkvgSurface;
+typedef struct _vkvg_surface_t *VkvgSurface;
/**
* @brief Opaque pointer on a Vkvg device structure.
* @ingroup device
*
* A #VkvgDevice is required for creating new surfaces.
*/
-typedef struct _vkvg_device_t* VkvgDevice;
+typedef struct _vkvg_device_t *VkvgDevice;
/**
* @brief Opaque pointer on a Vkvg pattern structure.
* @ingroup pattern
* Patterns are images to be drawn on surface with several
* configurable parameters such as the wrap mode, the filtering, etc...
*/
-typedef struct _vkvg_pattern_t* VkvgPattern;
+typedef struct _vkvg_pattern_t *VkvgPattern;
#if VKVG_DBG_STATS
/**
* @brief vkvg memory and vulkan statistiques.
- *
+ *
* @ingroup device
*/
typedef struct {
- uint32_t sizePoints; /**< maximum point array size */
- uint32_t sizePathes; /**< maximum path array size */
- uint32_t sizeVertices; /**< maximum size of host vertice cache */
- uint32_t sizeIndices; /**< maximum size of host index cache */
- uint32_t sizeVBO; /**< maximum size of vulkan vertex buffer */
- uint32_t sizeIBO; /**< maximum size of vulkan index buffer */
+ uint32_t sizePoints; /**< maximum point array size */
+ uint32_t sizePathes; /**< maximum path array size */
+ uint32_t sizeVertices; /**< maximum size of host vertice cache */
+ uint32_t sizeIndices; /**< maximum size of host index cache */
+ uint32_t sizeVBO; /**< maximum size of vulkan vertex buffer */
+ uint32_t sizeIBO; /**< maximum size of vulkan index buffer */
} vkvg_debug_stats_t;
-vkvg_debug_stats_t vkvg_device_get_stats (VkvgDevice dev);
-vkvg_debug_stats_t vkvg_device_reset_stats (VkvgDevice dev);
+vkvg_debug_stats_t vkvg_device_get_stats(VkvgDevice dev);
+vkvg_debug_stats_t vkvg_device_reset_stats(VkvgDevice dev);
#endif
-
/**
* @defgroup matrix Matrices
* @brief Generic matrix operations
* This is the reference documentation for handling matrices to use as transformation in drawing operations.
* Matrix computations in vkvg are taken from the cairo library.
* @{ */
-#define VKVG_IDENTITY_MATRIX (vkvg_matrix_t){1,0,0,1,0,0}/*!< The identity matrix*/
+#define VKVG_IDENTITY_MATRIX \
+ (vkvg_matrix_t) { 1, 0, 0, 1, 0, 0 } /*!< The identity matrix*/
/**
* @brief vkvg matrix structure
*
* @y0: Y translation component of the affine transformation
*/
typedef struct {
- float xx; float yx;
- float xy; float yy;
- float x0; float y0;
+ float xx;
+ float yx;
+ float xy;
+ float yy;
+ float x0;
+ float y0;
} vkvg_matrix_t;
/**
* @brief Set matrix to identity
* Initialize members of the supplied #vkvg_matrix_t to make an identity matrix of it.
* @param matrix a valid #vkvg_matrix_t pointer.
*/
-vkvg_public
-void vkvg_matrix_init_identity (vkvg_matrix_t *matrix);
+vkvg_public void vkvg_matrix_init_identity(vkvg_matrix_t *matrix);
/**
* @brief Matrix initialization.
*
* @param x0 X translation component of the affine transformation
* @param y0 Y translation component of the affine transformation
*/
-vkvg_public
-void vkvg_matrix_init (vkvg_matrix_t *matrix,
- float xx, float yx,
- float xy, float yy,
- float x0, float y0);
+vkvg_public void vkvg_matrix_init(vkvg_matrix_t *matrix, float xx, float yx, float xy, float yy, float x0, float y0);
/**
* @brief Rotation matrix initialization
*
* @param tx translation in the X direction
* @param ty translation in the Y direction
*/
-vkvg_public
-void vkvg_matrix_init_translate (vkvg_matrix_t *matrix, float tx, float ty);
+vkvg_public void vkvg_matrix_init_translate(vkvg_matrix_t *matrix, float tx, float ty);
/**
* @brief scaling matrix initialization
*
* @param sx scale in the x direction
* @param sy Scale in the y direction
*/
-vkvg_public
-void vkvg_matrix_init_scale (vkvg_matrix_t *matrix, float sx, float sy);
+vkvg_public void vkvg_matrix_init_scale(vkvg_matrix_t *matrix, float sx, float sy);
/**
* @brief rotation matrix initialization
*
* axis orientation of vkvg, positive angles rotate in a clockwise
* direction.
*/
-vkvg_public
-void vkvg_matrix_init_rotate (vkvg_matrix_t *matrix, float radians);
+vkvg_public void vkvg_matrix_init_rotate(vkvg_matrix_t *matrix, float radians);
/**
* @brief apply translation on matrix
*
* @param tx translation in the x direction
* @param ty translation in the y direction
*/
-vkvg_public
-void vkvg_matrix_translate (vkvg_matrix_t *matrix, float tx, float ty);
+vkvg_public void vkvg_matrix_translate(vkvg_matrix_t *matrix, float tx, float ty);
/**
* @brief apply scale on matrix
*
* @param sx scale in the x direction
* @param sy scale in the y direction
*/
-vkvg_public
-void vkvg_matrix_scale (vkvg_matrix_t *matrix, float sx, float sy);
+vkvg_public void vkvg_matrix_scale(vkvg_matrix_t *matrix, float sx, float sy);
/**
* @brief apply rotation on matrix
*
* rotate in the direction from the positive X axis toward the positive Y axis.
* With the default axis orientation of cairo, positive angles rotate in a clockwise direction.
*/
-vkvg_public
-void vkvg_matrix_rotate (vkvg_matrix_t *matrix, float radians);
+vkvg_public void vkvg_matrix_rotate(vkvg_matrix_t *matrix, float radians);
/**
* @brief matrices multiplication
*
* @param a first operand of the multiplication
* @param b second operand of the multiplication
*/
-vkvg_public
-void vkvg_matrix_multiply (vkvg_matrix_t *result, const vkvg_matrix_t *a, const vkvg_matrix_t *b);
+vkvg_public void vkvg_matrix_multiply(vkvg_matrix_t *result, const vkvg_matrix_t *a, const vkvg_matrix_t *b);
/**
* @brief transform distances
*
- * Transforms the distance vector (dx ,dy ) by matrix . This is similar to #cairo_matrix_transform_point() except that the translation
- * components of the transformation are ignored. The calculation of the returned vector is as follows:
+ * Transforms the distance vector (dx ,dy ) by matrix . This is similar to #cairo_matrix_transform_point() except that
+ * the translation components of the transformation are ignored. The calculation of the returned vector is as follows:
* @code
* dx2 = dx1 * a + dy1 * c;
* dy2 = dx1 * b + dy1 * d;
* @endcode
- * Affine transformations are position invariant, so the same vector always transforms to the same vector. If (x1 ,y1 ) transforms to (x2 ,y2 )
- * then (x1 +dx1 ,y1 +dy1 ) will transform to (x1 +dx2 ,y1 +dy2 ) for all values of x1 and x2 .
+ * Affine transformations are position invariant, so the same vector always transforms to the same vector. If (x1 ,y1 )
+ * transforms to (x2 ,y2 ) then (x1 +dx1 ,y1 +dy1 ) will transform to (x1 +dx2 ,y1 +dy2 ) for all values of x1 and x2 .
* @param matrix a valid #vkvg_matrix_t to use to transform distance
* @param dx X component of a distance vector. An in/out parameter
* @param dy Y component of a distance vector. An in/out parameter
*/
-vkvg_public
-void vkvg_matrix_transform_distance (const vkvg_matrix_t *matrix, float *dx, float *dy);
+vkvg_public void vkvg_matrix_transform_distance(const vkvg_matrix_t *matrix, float *dx, float *dy);
/**
* @brief transform point
*
* @param x X position. An in/out parameter
* @param y Y position. An in/out parameter
*/
-vkvg_public
-void vkvg_matrix_transform_point (const vkvg_matrix_t *matrix, float *x, float *y);
+vkvg_public void vkvg_matrix_transform_point(const vkvg_matrix_t *matrix, float *x, float *y);
/**
* @brief invert matrix
*
* @return If matrix has an inverse, modifies matrix to be the inverse matrix and returns VKVG_STATUS_SUCCESS.
* Otherwise, returns VKVG_STATUS_INVALID_MATRIX.
*/
-vkvg_public
-vkvg_status_t vkvg_matrix_invert (vkvg_matrix_t *matrix);
-vkvg_public
-void vkvg_matrix_get_scale (const vkvg_matrix_t *matrix, float *sx, float *sy);
+vkvg_public vkvg_status_t vkvg_matrix_invert(vkvg_matrix_t *matrix);
+vkvg_public void vkvg_matrix_get_scale(const vkvg_matrix_t *matrix, float *sx, float *sy);
/** @}*/
/*!
*/
typedef struct {
VkSampleCountFlags samples;
- bool deferredResolve;
- VkInstance inst;
- VkPhysicalDevice phy;
- VkDevice vkdev;
- uint32_t qFamIdx;
- uint32_t qIndex;
-}vkvg_device_create_info_t;
+ bool deferredResolve;
+ VkInstance inst;
+ VkPhysicalDevice phy;
+ VkDevice vkdev;
+ uint32_t qFamIdx;
+ uint32_t qIndex;
+} vkvg_device_create_info_t;
/**
* @brief Set device ready for multithreading.
*
* If thread aware mode is set to true,
*
- * This method should be called only once on device creation. If this method is called while some surfaces or patterns are
- * in use, this could have unexpected results.
+ * This method should be called only once on device creation. If this method is called while some surfaces or patterns
+ * are in use, this could have unexpected results.
*
*
* @param dev
* @param thread_awayre
*/
+vkvg_public void vkvg_device_set_thread_aware(VkvgDevice dev, uint32_t thread_awayre);
vkvg_public
-void vkvg_device_set_thread_aware (VkvgDevice dev, uint32_t thread_awayre);
-vkvg_public
-/**
- * @brief Set maximum cached context count.
- *
- * The context cache stored destroyed contexts per thread to speed-up new context creation.
- * To disable context cache, call this method with maxCount=0.
- *
- * @param dev A valid vkvg device pointer.
- * @param maxCount The maximum count of saved contexts for fast context instanciation.
- */
-void vkvg_device_set_context_cache_size (VkvgDevice dev, uint32_t maxCount);
+ /**
+ * @brief Set maximum cached context count.
+ *
+ * The context cache stored destroyed contexts per thread to speed-up new context creation.
+ * To disable context cache, call this method with maxCount=0.
+ *
+ * @param dev A valid vkvg device pointer.
+ * @param maxCount The maximum count of saved contexts for fast context instanciation.
+ */
+ void
+ vkvg_device_set_context_cache_size(VkvgDevice dev, uint32_t maxCount);
/**
* @brief Create a new vkvg device.
*
* - VKVG_STATUS_NULL_POINTER: vulkan function pointer fetching failed.
*
* @param samples The sample count that will be setup for the surfaces created by this device.
- * @param deferredResolve If true, the final simple sampled image of the surface will only be resolved on demand with a call
- * to #vkvg_surface_resolve() or
+ * @param deferredResolve If true, the final simple sampled image of the surface will only be resolved on demand with a
+ * call to #vkvg_surface_resolve() or
*/
-vkvg_public
-VkvgDevice vkvg_device_create (vkvg_device_create_info_t* info);
+vkvg_public VkvgDevice vkvg_device_create(vkvg_device_create_info_t *info);
/**
* @brief Create a new vkvg device from an existing vulkan logical device.
*
* Vkvg Devices has to stay active as long as surfaces created by it are used.
* @param dev The vkvg device to destroy.
*/
-vkvg_public
-void vkvg_device_destroy (VkvgDevice dev);
+vkvg_public void vkvg_device_destroy(VkvgDevice dev);
/**
* @brief Get the current status of the device.
*
* @param dev a valid vkvg device pointer.
* @return current state.
*/
-vkvg_public
-vkvg_status_t vkvg_device_status (VkvgDevice dev);
+vkvg_public vkvg_status_t vkvg_device_status(VkvgDevice dev);
/**
* @brief Increment the reference count on this device.
*
* @param The vkvg device pointer to increment the reference count for.
* @return
*/
-vkvg_public
-VkvgDevice vkvg_device_reference (VkvgDevice dev);
+vkvg_public VkvgDevice vkvg_device_reference(VkvgDevice dev);
/**
* @brief Query the reference count of the device.
*
* @param dev The vkvg device to get the reference count for.
* @return The reference count on this device.
*/
-vkvg_public
-uint32_t vkvg_device_get_reference_count (VkvgDevice dev);
+vkvg_public uint32_t vkvg_device_get_reference_count(VkvgDevice dev);
/**
* @brief Set the screen dot per inch for this device.
*
* @param hdpy Horizontal dot per inch.
* @param vdpy Vertical dot per inch.
*/
-vkvg_public
-void vkvg_device_set_dpy (VkvgDevice dev, int hdpy, int vdpy);
+vkvg_public void vkvg_device_set_dpy(VkvgDevice dev, int hdpy, int vdpy);
/**
* @brief Get the current dpy values.
*
* @param hdpy The current horizontal dot per inch.
* @param vdpy The current vertical dot per inch.
*/
-vkvg_public
-void vkvg_device_get_dpy (VkvgDevice dev, int* hdpy, int* vdpy);
+vkvg_public void vkvg_device_get_dpy(VkvgDevice dev, int *hdpy, int *vdpy);
/**
* @brief query required instance extensions for vkvg.
* by calling this method with pExtension being a NULL pointer.
* @param pExtCount a valid pointer to an integer that will be fill with the required extension count.
*/
-vkvg_public
-void vkvg_get_required_instance_extensions (const char** pExtensions, uint32_t* pExtCount);
+vkvg_public void vkvg_get_required_instance_extensions(const char **pExtensions, uint32_t *pExtCount);
/**
* @brief query required device extensions for vkvg.
* @param phy the vulkan physical device that will be used to create the @ref VkvgDevice.
* by calling this method with pExtension being a NULL pointer.
* @param pExtCount a valid pointer to an integer that will be fill with the required extension count.
* @return #VKVG_STATUS_SUCCESS or #VKVG_STATUS_DEVICE_ERROR if a fatal error occured.
-*/
-vkvg_public
-vkvg_status_t vkvg_get_required_device_extensions(VkPhysicalDevice phy, const char** pExtensions, uint32_t* pExtCount);
+ */
+vkvg_public vkvg_status_t vkvg_get_required_device_extensions(VkPhysicalDevice phy, const char **pExtensions,
+ uint32_t *pExtCount);
/**
* @brief get vulkan device creation requirement to fit vkvg needs.
*
* @return the required pNext chain for the vulkan device creation. The first structure is guarantied to
* be VkPhysicalDeviceVulkan12Features if vulkan version is >= 1.2
*/
-vkvg_public
-const void* vkvg_get_device_requirements (VkPhysicalDeviceFeatures* pEnabledFeatures);
+vkvg_public const void *vkvg_get_device_requirements(VkPhysicalDeviceFeatures *pEnabledFeatures);
/** @}*/
/** @addtogroup surface
* @param height Height in pixel of the surface to create.
* @return The new vkvg surface pointer, or null if an error occured.
*/
-vkvg_public
-VkvgSurface vkvg_surface_create (VkvgDevice dev, uint32_t width, uint32_t height);
+vkvg_public VkvgSurface vkvg_surface_create(VkvgDevice dev, uint32_t width, uint32_t height);
/**
* @brief Create a new vkvg surface by loading an image file.
* The resulting surface will have the same dimension as the supplied image.
* @param filePath The path of the image to load for creating the surface.
* @return The new vkvg surface with the loaded image as content, or null if an error occured.
*/
-vkvg_public
-VkvgSurface vkvg_surface_create_from_image (VkvgDevice dev, const char* filePath);
+vkvg_public VkvgSurface vkvg_surface_create_from_image(VkvgDevice dev, const char *filePath);
/**
* @brief Create a new vkvg surface using an existing vulkan texture as backend.
* This method will always return a valid pointer.
* @param vkhImg The VkhImage to use as the backend texture for drawing operations.
* @return A new surface, or null if an error occured.
*/
-vkvg_public
-VkvgSurface vkvg_surface_create_for_VkhImage (VkvgDevice dev, void* vkhImg);
+vkvg_public VkvgSurface vkvg_surface_create_for_VkhImage(VkvgDevice dev, void *vkhImg);
/**
* @brief Create a new vkvg surface from an in memory rgba bitmap
* @param dev The vkvg device used for creating the surface.
* @param height the height of the provided bitmap.
* @return
*/
-vkvg_public
-VkvgSurface vkvg_surface_create_from_bitmap (VkvgDevice dev, unsigned char* img, uint32_t width, uint32_t height);
+vkvg_public VkvgSurface vkvg_surface_create_from_bitmap(VkvgDevice dev, unsigned char *img, uint32_t width,
+ uint32_t height);
/**
* @brief Increment reference count on the surface by one.
* @param The vkvg surface to increment the reference count for.
* @return ?
*/
-vkvg_public
-VkvgSurface vkvg_surface_reference (VkvgSurface surf);
+vkvg_public VkvgSurface vkvg_surface_reference(VkvgSurface surf);
/**
* @brief Get the current reference count on this surface.
* @param The vkvg surface to get the reference count for.
* @return The reference count on the surface.
*/
-vkvg_public
-uint32_t vkvg_surface_get_reference_count (VkvgSurface surf);
+vkvg_public uint32_t vkvg_surface_get_reference_count(VkvgSurface surf);
/**
* @brief Decrement the reference count on the surface by one. Destroy it if count reach 0.
* @param The vkvg surface to destroy.
*/
-vkvg_public
-void vkvg_surface_destroy (VkvgSurface surf);
+vkvg_public void vkvg_surface_destroy(VkvgSurface surf);
/**
* @brief Query the current status of the surface.
* @param The vkvg surface to query the status for.
* @return The current surface status.
*/
-vkvg_public
-vkvg_status_t vkvg_surface_status (VkvgSurface surf);
+vkvg_public vkvg_status_t vkvg_surface_status(VkvgSurface surf);
/**
* @brief Clear surface's content.
*
* function of the context that will try to use the render pass load operations when possible.
* @param The surface to clear.
*/
-vkvg_public
-void vkvg_surface_clear (VkvgSurface surf);
+vkvg_public void vkvg_surface_clear(VkvgSurface surf);
/**
* @brief Get the final single sampled vulkan image of this surface.
* @param The vkvg surface to get the vulkan texture of.
* @return The VkImage object containing the result of the drawing operations on the surface.
*/
-vkvg_public
-VkImage vkvg_surface_get_vk_image (VkvgSurface surf);
+vkvg_public VkImage vkvg_surface_get_vk_image(VkvgSurface surf);
/**
* @brief Get the vulkan format of the vulkan texture used as backend for this surface.
* @param The surface to get the format for.
* @return The VkFormat.
*/
-vkvg_public
-VkFormat vkvg_surface_get_vk_format (VkvgSurface surf);
+vkvg_public VkFormat vkvg_surface_get_vk_format(VkvgSurface surf);
/**
* @brief Get the actual surface width.
* @param The vkvg surface to get the width for.
* @return The width in pixel of the surface.
*/
-vkvg_public
-uint32_t vkvg_surface_get_width (VkvgSurface surf);
+vkvg_public uint32_t vkvg_surface_get_width(VkvgSurface surf);
/**
* @brief Get the actual surface height.
* @param The vkvg surface to get the height for.
* @return The height in pixel of the surface.
*/
-vkvg_public
-uint32_t vkvg_surface_get_height (VkvgSurface surf);
+vkvg_public uint32_t vkvg_surface_get_height(VkvgSurface surf);
/**
* @brief Write surface content to a png file on disk.
* @param The surface to save on disk.
* @param The png file path.
* @return SUCCESS or not.
*/
-vkvg_public
-vkvg_status_t vkvg_surface_write_to_png (VkvgSurface surf, const char* path);
+vkvg_public vkvg_status_t vkvg_surface_write_to_png(VkvgSurface surf, const char *path);
/**
* @brief Save surface to memory
* @param The surface to save
* @param A valid pointer on cpu memory large enough to contain surface pixels (stride * height)
* @return SUCCESS or not.
*/
-vkvg_public
-vkvg_status_t vkvg_surface_write_to_memory (VkvgSurface surf, unsigned char* const bitmap);
+vkvg_public vkvg_status_t vkvg_surface_write_to_memory(VkvgSurface surf, unsigned char *const bitmap);
/**
* @brief Explicitly resolve a multisampled surface.
*
* Multisampled surfaces are backed internally by 2 vulkan textures, one multisampled for internal use only, and one
* single sampled texture onto which the multisampled one is resolved.
* If #VkvgDevice is created with `deferredResolve` set to `false`, multisampled image is automatically resolved on each
- * draw call. If `deferredResolve` is set to `true`, multisampled image will be resolved only with a call to #vkvg_surface_resolve() or
- * by a call to #vkvg_surface_get_vk_image().
+ * draw call. If `deferredResolve` is set to `true`, multisampled image will be resolved only with a call to
+ * #vkvg_surface_resolve() or by a call to #vkvg_surface_get_vk_image().
*
* @param surf The multisampled surface to resolve.
*/
-vkvg_public
-void vkvg_surface_resolve (VkvgSurface surf);
+vkvg_public void vkvg_surface_resolve(VkvgSurface surf);
/** @}*/
-//mimic from cairo, to facilitate usage of vkvg as cairo vulkan backend
+// mimic from cairo, to facilitate usage of vkvg as cairo vulkan backend
/**
* @brief compositing operators
* define the operation used to draw
*/
typedef enum _vkvg_operator {
- VKVG_OPERATOR_CLEAR,
+ VKVG_OPERATOR_CLEAR,
- VKVG_OPERATOR_SOURCE,
- VKVG_OPERATOR_OVER,
-/* VKVG_OPERATOR_IN,
- VKVG_OPERATOR_OUT,
- VKVG_OPERATOR_ATOP,
+ VKVG_OPERATOR_SOURCE,
+ VKVG_OPERATOR_OVER,
+ /* VKVG_OPERATOR_IN,
+ VKVG_OPERATOR_OUT,
+ VKVG_OPERATOR_ATOP,
- VKVG_OPERATOR_DEST,
- VKVG_OPERATOR_DEST_OVER,
- VKVG_OPERATOR_DEST_IN,
- VKVG_OPERATOR_DEST_OUT,
- VKVG_OPERATOR_DEST_ATOP,
+ VKVG_OPERATOR_DEST,
+ VKVG_OPERATOR_DEST_OVER,
+ VKVG_OPERATOR_DEST_IN,
+ VKVG_OPERATOR_DEST_OUT,
+ VKVG_OPERATOR_DEST_ATOP,
- VKVG_OPERATOR_XOR,
- VKVG_OPERATOR_ADD,
- VKVG_OPERATOR_SATURATE,
+ VKVG_OPERATOR_XOR,
+ VKVG_OPERATOR_ADD,
+ VKVG_OPERATOR_SATURATE,
- VKVG_OPERATOR_MULTIPLY,
- VKVG_OPERATOR_SCREEN,
- VKVG_OPERATOR_OVERLAY,
- VKVG_OPERATOR_DARKEN,
- VKVG_OPERATOR_LIGHTEN,
- VKVG_OPERATOR_COLOR_DODGE,
- VKVG_OPERATOR_COLOR_BURN,
- VKVG_OPERATOR_HARD_LIGHT,
- VKVG_OPERATOR_SOFT_LIGHT,
- */VKVG_OPERATOR_DIFFERENCE,/*
- VKVG_OPERATOR_EXCLUSION,
- VKVG_OPERATOR_HSL_HUE,
- VKVG_OPERATOR_HSL_SATURATION,
- VKVG_OPERATOR_HSL_COLOR,
- VKVG_OPERATOR_HSL_LUMINOSITY,*/
- VKVG_OPERATOR_MAX,
+ VKVG_OPERATOR_MULTIPLY,
+ VKVG_OPERATOR_SCREEN,
+ VKVG_OPERATOR_OVERLAY,
+ VKVG_OPERATOR_DARKEN,
+ VKVG_OPERATOR_LIGHTEN,
+ VKVG_OPERATOR_COLOR_DODGE,
+ VKVG_OPERATOR_COLOR_BURN,
+ VKVG_OPERATOR_HARD_LIGHT,
+ VKVG_OPERATOR_SOFT_LIGHT,
+ */
+ VKVG_OPERATOR_DIFFERENCE, /*
+ VKVG_OPERATOR_EXCLUSION,
+ VKVG_OPERATOR_HSL_HUE,
+ VKVG_OPERATOR_HSL_SATURATION,
+ VKVG_OPERATOR_HSL_COLOR,
+ VKVG_OPERATOR_HSL_LUMINOSITY,*/
+ VKVG_OPERATOR_MAX,
} vkvg_operator_t;
/** @addtogroup context
/**
* @brief Create a new vkvg context used for drawing on surfaces.
*
- * Creates a new #VkvgContext with all graphics state parameters set to default values and with surf as a target surface.
- * This method will always return a valid pointer even if memory allocation failed.
- * @remark This function references surf, so you can immediately call #vkvg_surface_destroy() on it if you don't need to maintain a separate reference to it.
+ * Creates a new #VkvgContext with all graphics state parameters set to default values and with surf as a target
+ * surface. This method will always return a valid pointer even if memory allocation failed.
+ * @remark This function references surf, so you can immediately call #vkvg_surface_destroy() on it if you don't need to
+ * maintain a separate reference to it.
* @param surf The target surface of the drawing operations.
* @return A new #VkvgContext or null if an error occured.
*/
-vkvg_public
-VkvgContext vkvg_create (VkvgSurface surf);
+vkvg_public VkvgContext vkvg_create(VkvgSurface surf);
/**
* @brief Destroy vkvg context.
*
* Decrement the reference count on the context by one. Destroy it if count reach 0.
* @param ctx The vkvg context to destroy.
*/
-vkvg_public
-void vkvg_destroy (VkvgContext ctx);
+vkvg_public void vkvg_destroy(VkvgContext ctx);
/**
* @brief Get context status.
*
*
* @param ctx The vkvg context to query the status for.
*/
-vkvg_public
-vkvg_status_t vkvg_status (VkvgContext ctx);
+vkvg_public vkvg_status_t vkvg_status(VkvgContext ctx);
/**
* vkvg_status_to_string:
* @status: a vkvg status
*
* Returns: a string representation of the status
**/
-vkvg_public
-const char* vkvg_status_to_string (vkvg_status_t status);
+vkvg_public const char *vkvg_status_to_string(vkvg_status_t status);
/**
* @brief Increment by one the reference count on this context.
* @param ctx The context to increment the reference count for.
* @return
*/
-vkvg_public
-VkvgContext vkvg_reference (VkvgContext ctx);
+vkvg_public VkvgContext vkvg_reference(VkvgContext ctx);
/**
* @brief Get the current reference count of this context.
* @param The vkvg context to query.
* @return The current reference count for this context.
*/
-vkvg_public
-uint32_t vkvg_get_reference_count (VkvgContext ctx);
+vkvg_public uint32_t vkvg_get_reference_count(VkvgContext ctx);
/**
* @brief Perform all the pending drawing operations on a context.
*
* The context is automatically flushed on destruction.
* @param ctx The vkvg context to flush.
*/
-vkvg_public
-void vkvg_flush (VkvgContext ctx);
+vkvg_public void vkvg_flush(VkvgContext ctx);
/**
* @brief Start a new empty path.
*
* The current position is reseted to (0,0).
* @param ctx The vkvg context pointer.
*/
-vkvg_public
-void vkvg_new_path (VkvgContext ctx);
+vkvg_public void vkvg_new_path(VkvgContext ctx);
/**
* @brief Close the current path.
*
* than 2.
* @param ctx The vkvg context pointer.
*/
-vkvg_public
-void vkvg_close_path (VkvgContext ctx);
+vkvg_public void vkvg_close_path(VkvgContext ctx);
/**
* @brief Start a new sub path.
*
* In many cases, this call is not needed since new sub-paths are frequently started with #vkvg_move_to().
* @param ctx The vkvg context pointer.
*/
-vkvg_public
-void vkvg_new_sub_path (VkvgContext ctx);
+vkvg_public void vkvg_new_sub_path(VkvgContext ctx);
/**
* @brief vkvg_path_extents
* @param ctx a valid @ref context
* @param x2 right of the resulting extents
* @param y2 bottom of the resulting extents
*/
-vkvg_public
-void vkvg_path_extents (VkvgContext ctx, float *x1, float *y1, float *x2, float *y2);
+vkvg_public void vkvg_path_extents(VkvgContext ctx, float *x1, float *y1, float *x2, float *y2);
/**
* @brief Get the current point.
*
* @param x A valid float pointer to receive the x coordinate of the current point.
* @param y A valid float pointer to receive the y coordinate of the current point.
*/
-vkvg_public
-void vkvg_get_current_point (VkvgContext ctx, float* x, float* y);
+vkvg_public void vkvg_get_current_point(VkvgContext ctx, float *x, float *y);
/**
* @brief Add a line to the current path from the current point to the coordinate given in arguments.
*
* @param x absolute x coordinate of second point
* @param y aboslute y coordinate of second point
*/
-vkvg_public
-void vkvg_line_to (VkvgContext ctx, float x, float y);
+vkvg_public void vkvg_line_to(VkvgContext ctx, float x, float y);
/**
* @brief Add a line to the current path from the current point to the coordinate relative to it.
*
* @param dx delta x
* @param dy delta y
*/
-vkvg_public
-void vkvg_rel_line_to (VkvgContext ctx, float dx, float dy);
+vkvg_public void vkvg_rel_line_to(VkvgContext ctx, float dx, float dy);
/**
* @brief Move the context pen to the position given in argument.
*
* @param x new x position of the pen
* @param y new y position of the pen
*/
-vkvg_public
-void vkvg_move_to (VkvgContext ctx, float x, float y);
+vkvg_public void vkvg_move_to(VkvgContext ctx, float x, float y);
/**
* @brief Move the context pen relative to the current point.
*
* @param x delta in the horizontal direction.
* @param y delta in the vertical direction.
*/
-vkvg_public
-void vkvg_rel_move_to (VkvgContext ctx, float x, float y);
+vkvg_public void vkvg_rel_move_to(VkvgContext ctx, float x, float y);
/**
* @brief Adds a circular arc of the given radius to the current path.
*
- * Adds a circular arc in clockwise order of the given radius to the current path following angles of a trigonometric circle.
- * After this call the current point will be the last computed point of the arc.
- * The arc is centered at (xc , yc ), begins at angle a1 and proceeds in the direction of increasing angles to end at angle a2.
- * If a2 is less than a1, it will be progressively increased by 2*PI until it is greater than a1.
+ * Adds a circular arc in clockwise order of the given radius to the current path following angles of a trigonometric
+ * circle. After this call the current point will be the last computed point of the arc. The arc is centered at (xc , yc
+ * ), begins at angle a1 and proceeds in the direction of increasing angles to end at angle a2. If a2 is less than a1,
+ * it will be progressively increased by 2*PI until it is greater than a1.
*
- * If there is a current point, an initial line segment will be added to the path to connect the current point to the beginning of the arc.
- * If this initial line is undesired, it can be avoided by calling vkvg_new_sub_path() before calling vkvg_arc().
+ * If there is a current point, an initial line segment will be added to the path to connect the current point to the
+ * beginning of the arc. If this initial line is undesired, it can be avoided by calling vkvg_new_sub_path() before
+ * calling vkvg_arc().
*
* Angles are measured in radians. An angle of 0.0 is in the direction of the positive X axis.
* An angle of PI/2 radians (90 degrees) is in the direction of the positive Y axis. Angles increase in the direction
- * from the positive X axis toward the positive Y axis. So with the default transformation matrix, angles increase in a clockwise direction.
+ * from the positive X axis toward the positive Y axis. So with the default transformation matrix, angles increase in a
+ * clockwise direction.
*
* @remark To convert from degrees to radians, use degrees * (PI/180).
* @param ctx The vkvg context pointer.
* @param a1 start angle in radians of the arc as if on a trigonometric circle.
* @param a2 end angle in radians of the arc to draw.
*/
-vkvg_public
-void vkvg_arc (VkvgContext ctx, float xc, float yc, float radius, float a1, float a2);
+vkvg_public void vkvg_arc(VkvgContext ctx, float xc, float yc, float radius, float a1, float a2);
/**
* @brief Add a circular arc in counter clockwise order to the current path.
*
- * Adds a circular arc in counter clockwise order of the given radius to the current path following angles of a trigonometric circle.
- * After this call the current point will be the last computed point of the arc.
- * The arc is centered at `(xc,yc)`, begins at angle `a1` and proceeds in the direction of decreasing angles to end at angle `a2`.
+ * Adds a circular arc in counter clockwise order of the given radius to the current path following angles of a
+ * trigonometric circle. After this call the current point will be the last computed point of the arc. The arc is
+ * centered at `(xc,yc)`, begins at angle `a1` and proceeds in the direction of decreasing angles to end at angle `a2`.
* If `a2` is greater than `a1`, it will be progressively decreased by `2*PI` until it is less than `a1`.
*
*
* @param a1 start angle in radians of the arc as if on a trigonometric circle.
* @param a2 end angle in radians of the arc to draw.
*/
-vkvg_public
-void vkvg_arc_negative (VkvgContext ctx, float xc, float yc, float radius, float a1, float a2);
+vkvg_public void vkvg_arc_negative(VkvgContext ctx, float xc, float yc, float radius, float a1, float a2);
/**
* @brief Adds a cubic Bézier spline to the current path.
*
- * Adds a cubic Bezier spline to the path from the current point to position (x3, y3), using (x1, y1) and (x2, y2) as the control points.
- * After this call the current point will be (x3, y3).
+ * Adds a cubic Bezier spline to the path from the current point to position (x3, y3), using (x1, y1) and (x2, y2) as
+ * the control points. After this call the current point will be (x3, y3).
*
- * If there is no current point before the call to vkvg_curve_to() this function will behave as if preceded by a call to vkvg_move_to(ctx, x1, y1).
+ * If there is no current point before the call to vkvg_curve_to() this function will behave as if preceded by a call to
+ * vkvg_move_to(ctx, x1, y1).
* @param ctx The vkvg context pointer.
* @param x1 The X coordinate of the first control point.
* @param y1 The Y coordinate of the first control point.
* @param x3 The X coordinate of the end of the curve.
* @param y3 The Y coordinate of the end of the curve.
*/
-vkvg_public
-void vkvg_curve_to (VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3);
+vkvg_public void vkvg_curve_to(VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3);
/**
* @brief Adds a cubic Bézier spline to the current path relative to the current point.
*
- * Adds a cubic Bézier spline to the path from the current point to position (x3, y3) in relative coordinate to the current point,
- * using (x1, y1) and (x2, y2) as the control points relative to the current point.
- * After this call the current point will be (x3, y3).
+ * Adds a cubic Bézier spline to the path from the current point to position (x3, y3) in relative coordinate to the
+ * current point, using (x1, y1) and (x2, y2) as the control points relative to the current point. After this call the
+ * current point will be (x3, y3).
*
* If there is no current point before the call to vkvg_rel_curve_to() => error:VKVG_STATUS_NO_CURRENT_POINT.
* @param ctx The vkvg context pointer.
* @param x3 The X coordinate of the end of the curve.
* @param y3 The Y coordinate of the end of the curve.
*/
-vkvg_public
-void vkvg_rel_curve_to (VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3);
+vkvg_public void vkvg_rel_curve_to(VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3);
/**
* @brief Add a quadratic Bezizer curve to the current path
*
- * If there is no current point before the call to vkvg_quadratic_to() this function will behave as if preceded by a call to vkvg_move_to(ctx, x1, y1).
+ * If there is no current point before the call to vkvg_quadratic_to() this function will behave as if preceded by a
+ * call to vkvg_move_to(ctx, x1, y1).
* @param ctx The vkvg context pointer.
* @param x1 The X coordinate of the control point.
* @param y1 The Y coordinate of the control point.
* @param x2 The X coordinate of the end point of the curve.
* @param y2 The Y coordinate of the end point of the curve.
*/
-vkvg_public
-void vkvg_quadratic_to (VkvgContext ctx, float x1, float y1, float x2, float y2);
+vkvg_public void vkvg_quadratic_to(VkvgContext ctx, float x1, float y1, float x2, float y2);
/**
* @brief Add a quadratic Bezizer curve to the current path relative to the current point
*
* @param x2 The X coordinate of the end point of the curve relative to the current point.
* @param y2 The Y coordinate of the end point of the curve relative to the current point.
*/
-vkvg_public
-void vkvg_rel_quadratic_to (VkvgContext ctx, float x1, float y1, float x2, float y2);
+vkvg_public void vkvg_rel_quadratic_to(VkvgContext ctx, float x1, float y1, float x2, float y2);
/**
* @brief Add an axis aligned rectangle subpath to the current path.
*
* @param h The height in pixel of the rectangle to draw.
* @return VKVG_STATUS_SUCCESS or VKVG_STATUS_INVALID_RECT if width or height is equal to 0.
*/
-vkvg_public
-vkvg_status_t vkvg_rectangle(VkvgContext ctx, float x, float y, float w, float h);
-/**
-* @brief Add an axis aligned rectangle with rounded corners to the current path.
-*
-* Adds a closed sub-path rectangle of the given size to the current path at position (x, y).
-* @param ctx The vkvg context pointer.
-* @param x The x coordinate of the top left corner of the rectangle to emit.
-* @param y The y coordinate of the top left corner of the rectangle to emit.
-* @param w The width in pixel of the rectangle to draw.
-* @param h The height in pixel of the rectangle to draw.
-* @param radius The radius of the corners.
-* @return VKVG_STATUS_SUCCESS or VKVG_STATUS_INVALID_RECT if width or height is equal to 0.
-*/
-vkvg_public
-vkvg_status_t vkvg_rounded_rectangle (VkvgContext ctx, float x, float y, float w, float h, float radius);
-/**
-* @brief Add an axis aligned rectangle with rounded corners defined in both axis to the current path.
-*
-* Adds a closed sub-path rectangle of the given size to the current path at position (x, y).
-* @param ctx The vkvg context pointer.
-* @param x The x coordinate of the top left corner of the rectangle to emit.
-* @param y The y coordinate of the top left corner of the rectangle to emit.
-* @param w The width in pixel of the rectangle to draw.
-* @param h The height in pixel of the rectangle to draw.
-* @param rx The horizontal radius of the corners.
-* @param ry The vertical radius of the corners.
-* @return VKVG_STATUS_SUCCESS or VKVG_STATUS_INVALID_RECT if width or height is equal to 0.
-*/
-vkvg_public
-void vkvg_rounded_rectangle2 (VkvgContext ctx, float x, float y, float w, float h, float rx, float ry);
+vkvg_public vkvg_status_t vkvg_rectangle(VkvgContext ctx, float x, float y, float w, float h);
+/**
+ * @brief Add an axis aligned rectangle with rounded corners to the current path.
+ *
+ * Adds a closed sub-path rectangle of the given size to the current path at position (x, y).
+ * @param ctx The vkvg context pointer.
+ * @param x The x coordinate of the top left corner of the rectangle to emit.
+ * @param y The y coordinate of the top left corner of the rectangle to emit.
+ * @param w The width in pixel of the rectangle to draw.
+ * @param h The height in pixel of the rectangle to draw.
+ * @param radius The radius of the corners.
+ * @return VKVG_STATUS_SUCCESS or VKVG_STATUS_INVALID_RECT if width or height is equal to 0.
+ */
+vkvg_public vkvg_status_t vkvg_rounded_rectangle(VkvgContext ctx, float x, float y, float w, float h, float radius);
+/**
+ * @brief Add an axis aligned rectangle with rounded corners defined in both axis to the current path.
+ *
+ * Adds a closed sub-path rectangle of the given size to the current path at position (x, y).
+ * @param ctx The vkvg context pointer.
+ * @param x The x coordinate of the top left corner of the rectangle to emit.
+ * @param y The y coordinate of the top left corner of the rectangle to emit.
+ * @param w The width in pixel of the rectangle to draw.
+ * @param h The height in pixel of the rectangle to draw.
+ * @param rx The horizontal radius of the corners.
+ * @param ry The vertical radius of the corners.
+ * @return VKVG_STATUS_SUCCESS or VKVG_STATUS_INVALID_RECT if width or height is equal to 0.
+ */
+vkvg_public void vkvg_rounded_rectangle2(VkvgContext ctx, float x, float y, float w, float h, float rx, float ry);
/**
* @brief Add a closed ellipse to the current path.
* @param y Ellipse's center y coordinate.
* @param rotationAngle A clockwise rotation angle in radian.
*/
-vkvg_public
-void vkvg_ellipse (VkvgContext ctx, float radiusX, float radiusY, float x, float y, float rotationAngle);
+vkvg_public void vkvg_ellipse(VkvgContext ctx, float radiusX, float radiusY, float x, float y, float rotationAngle);
/**
* @brief Add an elliptical arc to the current path.
*
- * Draws an elliptical arc from the current point to (x, y). The size and orientation of the ellipse are defined by two radii (rx, ry)
- * and an x-axis-rotation, which indicates how the ellipse as a whole is rotated relative to the current coordinate system.
- * The center (cx, cy) of the ellipse is calculated automatically to satisfy the constraints imposed by the other parameters.
- * For a given radii pair, there are two ellipses that could connect two random points. large-arc-flag and sweep-flag contribute
- * to the automatic calculations and help determine how the arc is drawn.
+ * Draws an elliptical arc from the current point to (x, y). The size and orientation of the ellipse are defined by two
+ * radii (rx, ry) and an x-axis-rotation, which indicates how the ellipse as a whole is rotated relative to the current
+ * coordinate system. The center (cx, cy) of the ellipse is calculated automatically to satisfy the constraints imposed
+ * by the other parameters. For a given radii pair, there are two ellipses that could connect two random points.
+ * large-arc-flag and sweep-flag contribute to the automatic calculations and help determine how the arc is drawn.
*
* @image html elliptical-arc-options.svg
*
* @param ry The y radius of the ellipse.
* @param phi Clockwise rotation of the arc in radian.
*/
-vkvg_public
-void vkvg_elliptic_arc_to (VkvgContext ctx, float x, float y, bool large_arc_flag, bool sweep_flag, float rx, float ry, float phi);
+vkvg_public void vkvg_elliptic_arc_to(VkvgContext ctx, float x, float y, bool large_arc_flag, bool sweep_flag, float rx,
+ float ry, float phi);
/**
* @brief Add an elliptical arc to the current path.
*
- * This method has the same effect as a call to #vkvg_elliptic_arc_to except that the coordinate are expressed relative to the current point.
+ * This method has the same effect as a call to #vkvg_elliptic_arc_to except that the coordinate are expressed relative
+ * to the current point.
* @param ctx A valid context handle.
* @param x the arc end point x coordinate relative to the current point.
* @param y the arc end point y coordinate relative to the current point.
* @param ry The y radius of the ellipse.
* @param phi Clockwise rotation of the arc in radian.
*/
-vkvg_public
-void vkvg_rel_elliptic_arc_to (VkvgContext ctx, float x, float y, bool large_arc_flag, bool sweep_flag, float rx, float ry, float phi);
+vkvg_public void vkvg_rel_elliptic_arc_to(VkvgContext ctx, float x, float y, bool large_arc_flag, bool sweep_flag,
+ float rx, float ry, float phi);
/**
* @brief Stroke command
*
- * A drawing operator that strokes the current path according to the current line width, line join, line cap, and dash settings.
- * After vkvg_stroke(), the current path will be cleared from the vkvg context. See #vkvg_set_line_width(), #vkvg_set_line_join(),
- * #vkvg_set_line_cap(), #vkvg_set_dash(), and #vkvg_stroke_preserve().
+ * A drawing operator that strokes the current path according to the current line width, line join, line cap, and dash
+ * settings. After vkvg_stroke(), the current path will be cleared from the vkvg context. See #vkvg_set_line_width(),
+ * #vkvg_set_line_join(), #vkvg_set_line_cap(), #vkvg_set_dash(), and #vkvg_stroke_preserve().
*
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_stroke (VkvgContext ctx);
+vkvg_public void vkvg_stroke(VkvgContext ctx);
/**
* @brief Stroke command that preserve current path.
*
*
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_stroke_preserve (VkvgContext ctx);
+vkvg_public void vkvg_stroke_preserve(VkvgContext ctx);
/**
* @brief Fill command
*
*
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_fill (VkvgContext ctx);
+vkvg_public void vkvg_fill(VkvgContext ctx);
/**
* @brief Fill command that preserve current path.
*
*
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_fill_preserve (VkvgContext ctx);
+vkvg_public void vkvg_fill_preserve(VkvgContext ctx);
/**
* @brief Paint command.
*
*
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_paint (VkvgContext ctx);
+vkvg_public void vkvg_paint(VkvgContext ctx);
/**
* @brief Clear surface.
*
* @remark To clear a surface not bound to a context, call #vkvg_surface_clear().
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_clear (VkvgContext ctx);//use vkClearAttachment to speed up clearing surf
+vkvg_public void vkvg_clear(VkvgContext ctx); // use vkClearAttachment to speed up clearing surf
/**
* @brief Reset the current clip region.
*
*
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_reset_clip (VkvgContext ctx);
+vkvg_public void vkvg_reset_clip(VkvgContext ctx);
/**
* @brief Establishes a new clip region.
*
- * Establishes a new clip region by intersecting the current clip region with the current path as it would be filled by @ref vkvg_fill() and
- * according to the current fill rule (@ref vkvg_set_fill_rule()).
+ * Establishes a new clip region by intersecting the current clip region with the current path as it would be filled by
+ * @ref vkvg_fill() and according to the current fill rule (@ref vkvg_set_fill_rule()).
*
- * The current clip region affects all drawing operations by effectively masking out any changes to the surface that are outside the current clip region.
+ * The current clip region affects all drawing operations by effectively masking out any changes to the surface that are
+ * outside the current clip region.
*
* After vkvg_clip(), the current path will be cleared from the context.
*
- * Calling vkvg_clip() can only make the clip region smaller, never larger. But the current clip is part of the graphics state,
- * so a temporary restriction of the clip region can be achieved by calling @ref vkvg_clip() within a @ref vkvg_save()/@ref vkvg_restore() pair.
- * The only other means of increasing the size of the clip region is @ref vkvg_reset_clip().
+ * Calling vkvg_clip() can only make the clip region smaller, never larger. But the current clip is part of the graphics
+ * state, so a temporary restriction of the clip region can be achieved by calling @ref vkvg_clip() within a @ref
+ * vkvg_save()/@ref vkvg_restore() pair. The only other means of increasing the size of the clip region is @ref
+ * vkvg_reset_clip().
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_clip (VkvgContext ctx);
+vkvg_public void vkvg_clip(VkvgContext ctx);
/**
* @brief Establishes a new clip region preserving the current path.
*
*
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_clip_preserve (VkvgContext ctx);
+vkvg_public void vkvg_clip_preserve(VkvgContext ctx);
/**
* @brief Set global opacity for drawing operations.
*
* @param ctx a valid context handle.
* @param opacity global opacity value between 0..1.
*/
+vkvg_public void vkvg_set_opacity(VkvgContext ctx, float opacity);
vkvg_public
-void vkvg_set_opacity (VkvgContext ctx, float opacity);
-vkvg_public
-/**
- * @brief Get current opacity.
- *
- * Retrieve the current opacity for the supplied context as set by a call to #vkvg_set_opacity().
- * @param ctx a valid context handle.
- * @return the current opacity of the supplied context.
- */
-float vkvg_get_opacity (VkvgContext ctx);
+ /**
+ * @brief Get current opacity.
+ *
+ * Retrieve the current opacity for the supplied context as set by a call to #vkvg_set_opacity().
+ * @param ctx a valid context handle.
+ * @return the current opacity of the supplied context.
+ */
+ float
+ vkvg_get_opacity(VkvgContext ctx);
/**
* @brief Set current source for drawing to the solid color defined by the supplied 32bit integer.
* @param ctx a valid vkvg @ref context
* @param rgba color coded in 32bit integer.
*/
-vkvg_public
-void vkvg_set_source_color (VkvgContext ctx, uint32_t c);
+vkvg_public void vkvg_set_source_color(VkvgContext ctx, uint32_t c);
/**
* @brief set color with alpha.
*
* @param b the blue component of the color.
* @param a the alpha component holding the transparency for the current color.
*/
-vkvg_public
-void vkvg_set_source_rgba (VkvgContext ctx, float r, float g, float b, float a);
+vkvg_public void vkvg_set_source_rgba(VkvgContext ctx, float r, float g, float b, float a);
/**
* @brief set opaque color as new source.
*
* @param b the blue component of the color.
* @param a the alpha component holding the transparency for the current color.
*/
-vkvg_public
-void vkvg_set_source_rgb (VkvgContext ctx, float r, float g, float b);
+vkvg_public void vkvg_set_source_rgb(VkvgContext ctx, float r, float g, float b);
/**
* @brief set line width for the next draw command.
*
* @param ctx a valid vkvg @ref context
* @param width new current line width for the context.
*/
-vkvg_public
-void vkvg_set_line_width (VkvgContext ctx, float width);
+vkvg_public void vkvg_set_line_width(VkvgContext ctx, float width);
/**
* @brief set line join miter size limit.
*
- * If the current line join style is set to VKVG_LINE_JOIN_MITER (see vkvg_set_line_join()), the miter limit is used to determine whether the lines should be
- * joined with a bevel instead of a miter. Vkvg divides the length of the miter by the line width. If the result is greater than the miter limit, the style is converted to a bevel.
+ * If the current line join style is set to VKVG_LINE_JOIN_MITER (see vkvg_set_line_join()), the miter limit is used to
+ * determine whether the lines should be joined with a bevel instead of a miter. Vkvg divides the length of the miter by
+ * the line width. If the result is greater than the miter limit, the style is converted to a bevel.
*
- * The default miter limit value is 10.0, which will convert joins with interior angles less than 11 degrees to bevels instead of miters.
- * For reference, a miter limit of 2.0 makes the miter cutoff at 60 degrees, and a miter limit of 1.414 makes the cutoff at 90 degrees.
+ * The default miter limit value is 10.0, which will convert joins with interior angles less than 11 degrees to bevels
+ * instead of miters. For reference, a miter limit of 2.0 makes the miter cutoff at 60 degrees, and a miter limit
+ * of 1.414 makes the cutoff at 90 degrees.
*
* A miter limit for a desired angle can be computed as: miter limit = 1/sin(angle/2)
*
* @param ctx a valid vkvg @ref context
* @param limit new current miter limit value for the context.
*/
-vkvg_public
-void vkvg_set_miter_limit (VkvgContext ctx, float limit);
+vkvg_public void vkvg_set_miter_limit(VkvgContext ctx, float limit);
/**
* @brief Gets the current miter limit.
*
* @param ctx a valid vkvg @ref context
* @return the current miter limit for the context.
*/
-vkvg_public
-float vkvg_get_miter_limit (VkvgContext ctx);
+vkvg_public float vkvg_get_miter_limit(VkvgContext ctx);
/**
* @brief set line terminations for the next draw command.
*
* @param ctx a valid vkvg @ref context
* @param cap new line termination, may be one of the value of #vkvg_line_cap_t.
*/
-vkvg_public
-void vkvg_set_line_cap (VkvgContext ctx, vkvg_line_cap_t cap);
+vkvg_public void vkvg_set_line_cap(VkvgContext ctx, vkvg_line_cap_t cap);
/**
* @brief set line joins for the next draw command.
*
* @param ctx a valid vkvg @ref context
* @param join new line join as defined in #vkvg_line_joint_t.
*/
-vkvg_public
-void vkvg_set_line_join (VkvgContext ctx, vkvg_line_join_t join);
+vkvg_public void vkvg_set_line_join(VkvgContext ctx, vkvg_line_join_t join);
/**
* @brief use supplied surface as current pattern.
*
* @param x an x offset to apply for drawing operations using this surface.
* @param y an y offset to apply for drawing operations using this surface.
*/
-vkvg_public
-void vkvg_set_source_surface (VkvgContext ctx, VkvgSurface surf, float x, float y);
+vkvg_public void vkvg_set_source_surface(VkvgContext ctx, VkvgSurface surf, float x, float y);
/**
* @brief set supplied pattern as current source.
*
* @param ctx a valid vkvg @ref context
* @param pat the new pattern to use as source for further drawing operations.
*/
-vkvg_public
-void vkvg_set_source (VkvgContext ctx, VkvgPattern pat);
+vkvg_public void vkvg_set_source(VkvgContext ctx, VkvgPattern pat);
/**
* @brief
*
* @param ctx a valid vkvg @ref context
* @param op
*/
-vkvg_public
-void vkvg_set_operator (VkvgContext ctx, vkvg_operator_t op);
+vkvg_public void vkvg_set_operator(VkvgContext ctx, vkvg_operator_t op);
/**
* @brief
*
* @param ctx a valid vkvg @ref context
* @param fr
*/
-vkvg_public
-void vkvg_set_fill_rule (VkvgContext ctx, vkvg_fill_rule_t fr);
+vkvg_public void vkvg_set_fill_rule(VkvgContext ctx, vkvg_fill_rule_t fr);
/**
* @brief set the dash configuration for strokes
*
* @param num_dashes the length of the dash array.
* @param offset an offset into the dash pattern at which the stroke should start.
*/
-vkvg_public
-void vkvg_set_dash (VkvgContext ctx, const float* dashes, uint32_t num_dashes, float offset);
+vkvg_public void vkvg_set_dash(VkvgContext ctx, const float *dashes, uint32_t num_dashes, float offset);
/**
* @brief get current dash settings.
*
* @param num_dashes[out] return length of dash array or 0 if dash is not set.
* @param offset[out] return value for the current dash offset
*/
-vkvg_public
-void vkvg_get_dash (VkvgContext ctx, const float *dashes, uint32_t* num_dashes, float* offset);
+vkvg_public void vkvg_get_dash(VkvgContext ctx, const float *dashes, uint32_t *num_dashes, float *offset);
/**
* @brief get current line width
* @param ctx a valid vkvg @ref context
* @return current line width.
*/
-vkvg_public
-float vkvg_get_line_width (VkvgContext ctx);
+vkvg_public float vkvg_get_line_width(VkvgContext ctx);
/**
* @brief
*
* @param ctx a valid vkvg @ref context
* @return vkvg_line_cap_t
*/
-vkvg_public
-vkvg_line_cap_t vkvg_get_line_cap (VkvgContext ctx);
+vkvg_public vkvg_line_cap_t vkvg_get_line_cap(VkvgContext ctx);
/**
* @brief
*
* @param ctx a valid vkvg @ref context
* @return vkvg_line_join_t
*/
-vkvg_public
-vkvg_line_join_t vkvg_get_line_join (VkvgContext ctx);
+vkvg_public vkvg_line_join_t vkvg_get_line_join(VkvgContext ctx);
/**
* @brief
*
* @param ctx a valid vkvg @ref context
* @return vkvg_operator_t
*/
-vkvg_public
-vkvg_operator_t vkvg_get_operator (VkvgContext ctx);
+vkvg_public vkvg_operator_t vkvg_get_operator(VkvgContext ctx);
/**
* @brief Get current fill rule.
*
* @param ctx a valid vkvg @ref context
* @return vkvg_fill_rule_t The current fill rule of the context.
*/
-vkvg_public
-vkvg_fill_rule_t vkvg_get_fill_rule (VkvgContext ctx);
+vkvg_public vkvg_fill_rule_t vkvg_get_fill_rule(VkvgContext ctx);
/**
* @brief Get the current source of the context.
*
* @param ctx a valid vkvg @ref context
* @return VkvgPattern The current context's source.
*/
-vkvg_public
-VkvgPattern vkvg_get_source (VkvgContext ctx);
+vkvg_public VkvgPattern vkvg_get_source(VkvgContext ctx);
/**
* @brief Get the current target of the context.
* @param ctx a valid vkvg @ref context
* @return The currently bound target surface.
*/
-vkvg_public
-VkvgSurface vkvg_get_target (VkvgContext ctx);
+vkvg_public VkvgSurface vkvg_get_target(VkvgContext ctx);
/**
* @brief Check if context has a current point defined.
*
* @param ctx a valig vkvg @ref context
* @return bool `true`if a current point is defined, `false` otherwise.
**/
-vkvg_public
-bool vkvg_has_current_point (VkvgContext ctx);
+vkvg_public bool vkvg_has_current_point(VkvgContext ctx);
/**
* @brief Save context's graphic states.
*
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_save (VkvgContext ctx);
+vkvg_public void vkvg_save(VkvgContext ctx);
/**
* @brief Restore context's graphic states.
*
*
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_restore (VkvgContext ctx);
+vkvg_public void vkvg_restore(VkvgContext ctx);
/**
* @brief Add a translation to the current transformation matrix.
*
- * Modifies the current transformation matrix by applying an additional translation transformation by (dx,dy) in user space coordinate.
+ * Modifies the current transformation matrix by applying an additional translation transformation by (dx,dy) in user
+ * space coordinate.
* @param ctx a valid vkvg @ref context
* @param dx the x translation
* @param dy the y translation
*/
-vkvg_public
-void vkvg_translate (VkvgContext ctx, float dx, float dy);
+vkvg_public void vkvg_translate(VkvgContext ctx, float dx, float dy);
/**
* @brief Add a scaling transform to the current transformation matrix.
*
- * Modifies the current transformation matrix by applying an additional scaling transformation by (sx,sy) in user space coordinate.
+ * Modifies the current transformation matrix by applying an additional scaling transformation by (sx,sy) in user space
+ * coordinate.
* @param ctx a valid vkvg @ref context
* @param sx scale in the x direction.
* @param sy scale in the y direction.
*/
-vkvg_public
-void vkvg_scale (VkvgContext ctx, float sx, float sy);
+vkvg_public void vkvg_scale(VkvgContext ctx, float sx, float sy);
/**
* @brief Add a rotation to the current transformation matrix.
*
* @param ctx a valid vkvg @ref context
* @param radians rotation angle in radian.
*/
-vkvg_public
-void vkvg_rotate (VkvgContext ctx, float radians);
+vkvg_public void vkvg_rotate(VkvgContext ctx, float radians);
/**
* @brief Add an additional transformation to the current matrix.
*
* @param ctx a valid vkvg @ref context
* @param matrix
*/
-vkvg_public
-void vkvg_transform (VkvgContext ctx, const vkvg_matrix_t* matrix);
+vkvg_public void vkvg_transform(VkvgContext ctx, const vkvg_matrix_t *matrix);
/**
* @brief Set the current matrix.
*
* @param ctx a valid vkvg @ref context
* @param matrix
*/
-vkvg_public
-void vkvg_set_matrix (VkvgContext ctx, const vkvg_matrix_t* matrix);
+vkvg_public void vkvg_set_matrix(VkvgContext ctx, const vkvg_matrix_t *matrix);
/**
* @brief Get the current matrix.
*
* @param ctx a valid vkvg @ref context
* @param matrix a valid #vkvg_matrix_t pointer to receive the current context's transform.
*/
-vkvg_public
-void vkvg_get_matrix (VkvgContext ctx, vkvg_matrix_t * const matrix);
+vkvg_public void vkvg_get_matrix(VkvgContext ctx, vkvg_matrix_t *const matrix);
/**
* @brief Set the current matrix to identity.
*
*
* @param ctx a valid vkvg @ref context
*/
-vkvg_public
-void vkvg_identity_matrix (VkvgContext ctx);
+vkvg_public void vkvg_identity_matrix(VkvgContext ctx);
/**
* @brief Try find font with the specified name using the FontConfig library.
* @param ctx a valid vkvg @ref context
* @param name A name to be recognized by the FontConfig library
*/
-vkvg_public
-void vkvg_select_font_face (VkvgContext ctx, const char* name);
+vkvg_public void vkvg_select_font_face(VkvgContext ctx, const char *name);
/**
* @brief Select a new font by providing its file path.
*
* @param path A valid font file path.
* @param name A short name to select this font afteward
*/
-vkvg_public
-void vkvg_load_font_from_path (VkvgContext ctx, const char* path, const char *name);
+vkvg_public void vkvg_load_font_from_path(VkvgContext ctx, const char *path, const char *name);
/**
* @brief Select a new font by providing a pointer on the font file loaded in memory and its size in byte.
*
* @param fontBufferByteSize the size of the font buffer in bytes.
* @param name A short name to select this font afteward
*/
-vkvg_public
-void vkvg_load_font_from_memory (VkvgContext ctx, unsigned char* fontBuffer, long fontBufferByteSize, const char* name);
+vkvg_public void vkvg_load_font_from_memory(VkvgContext ctx, unsigned char *fontBuffer, long fontBufferByteSize,
+ const char *name);
/**
* @brief
*
* @param ctx a valid vkvg @ref context
* @param size
*/
-vkvg_public
-void vkvg_set_font_size (VkvgContext ctx, uint32_t size);
+vkvg_public void vkvg_set_font_size(VkvgContext ctx, uint32_t size);
/**
* @brief Show a string of text.
*
* @param ctx a valid vkvg @ref context
* @param utf8 A null-terminated utf8 encoded string of text.
*/
-vkvg_public
-void vkvg_show_text (VkvgContext ctx, const char* utf8);
+vkvg_public void vkvg_show_text(VkvgContext ctx, const char *utf8);
/**
* @brief Gets the extents for a string of text.
*
* @param utf8 A null-terminated utf8 encoded string of text.
* @param extents
*/
-vkvg_public
-void vkvg_text_extents (VkvgContext ctx, const char* utf8, vkvg_text_extents_t* extents);
+vkvg_public void vkvg_text_extents(VkvgContext ctx, const char *utf8, vkvg_text_extents_t *extents);
/**
* @brief Gets the font extents for the currently selected font.
*
* @param ctx a valid vkvg @ref context
* @param extents A valid #vkvg_font_extents_t handle to be filled with current font extents.
*/
-vkvg_public
-void vkvg_font_extents (VkvgContext ctx, vkvg_font_extents_t* extents);
+vkvg_public void vkvg_font_extents(VkvgContext ctx, vkvg_font_extents_t *extents);
-//text run holds harfbuz datas, and prevent recreating them multiple times for the same line of text.
+// text run holds harfbuz datas, and prevent recreating them multiple times for the same line of text.
/**
* @brief Create a new text run.
*
* @param text Null terminated utf8 string.
* @return VkvgText
*/
-vkvg_public
-VkvgText vkvg_text_run_create (VkvgContext ctx, const char* text);
+vkvg_public VkvgText vkvg_text_run_create(VkvgContext ctx, const char *text);
/**
* @brief Create a new text run for a non null terminated string.
*
* @param length glyphs count, not to be confused with byte length.
* @return VkvgText
*/
-vkvg_public
-VkvgText vkvg_text_run_create_with_length (VkvgContext ctx, const char* text, uint32_t length);
+vkvg_public VkvgText vkvg_text_run_create_with_length(VkvgContext ctx, const char *text, uint32_t length);
/**
* @brief Release resources holded by the text run.
*
* @param VkvgtextRun A valid VkvgText pointer.
*/
-vkvg_public
-void vkvg_text_run_destroy (VkvgText textRun);
+vkvg_public void vkvg_text_run_destroy(VkvgText textRun);
/**
* @brief
*
* @param ctx a valid vkvg @ref context
* @param textRun
*/
-vkvg_public
-void vkvg_show_text_run (VkvgContext ctx, VkvgText textRun);
+vkvg_public void vkvg_show_text_run(VkvgContext ctx, VkvgText textRun);
/**
* @brief
*
* @param textRun
* @param extents
*/
-vkvg_public
-void vkvg_text_run_get_extents (VkvgText textRun, vkvg_text_extents_t* extents);
+vkvg_public void vkvg_text_run_get_extents(VkvgText textRun, vkvg_text_extents_t *extents);
/**
* @brief Get glyph count of text run.
*
* @return glyph count
*/
-vkvg_public
-uint32_t vkvg_text_run_get_glyph_count (VkvgText textRun);
+vkvg_public uint32_t vkvg_text_run_get_glyph_count(VkvgText textRun);
/**
* @brief retrieve glyph positions.
*
*/
-vkvg_public
-void vkvg_text_run_get_glyph_position (VkvgText textRun,
- uint32_t index,
- vkvg_glyph_info_t* pGlyphInfo);
+vkvg_public void vkvg_text_run_get_glyph_position(VkvgText textRun, uint32_t index, vkvg_glyph_info_t *pGlyphInfo);
/** @}*/
/**
* @param pat A valid pattern handle.
* @return The current status of the pattern.
*/
-vkvg_public
-vkvg_status_t vkvg_pattern_status (VkvgPattern pat);
+vkvg_public vkvg_status_t vkvg_pattern_status(VkvgPattern pat);
/**
* @brief add reference
*
* @param pat a valid #VkvgPattern pointer
* @return VkvgPattern
*/
-vkvg_public
-VkvgPattern vkvg_pattern_reference (VkvgPattern pat);
+vkvg_public VkvgPattern vkvg_pattern_reference(VkvgPattern pat);
/**
* @brief get reference count
*
* @param pat a valid #VkvgPattern to query for its reference count
* @return uint32_t the current reference count for this instance.
*/
-vkvg_public
-uint32_t vkvg_pattern_get_reference_count (VkvgPattern pat);
+vkvg_public uint32_t vkvg_pattern_get_reference_count(VkvgPattern pat);
/**
* @brief create a surface pattern
*
* @param surf a valid #VkvgSurface to use for pattern
* @return VkvgPattern a newly created pattern
*/
-vkvg_public
-VkvgPattern vkvg_pattern_create_for_surface (VkvgSurface surf);
+vkvg_public VkvgPattern vkvg_pattern_create_for_surface(VkvgSurface surf);
/**
* @brief create a new linear gradient.
*
* @param y1 y coordinate of the end point
* @return VkvgPattern the newly created pattern, call @ref vkvg_pattern_destroy when finished with it.
*/
-vkvg_public
-VkvgPattern vkvg_pattern_create_linear (float x0, float y0, float x1, float y1);
+vkvg_public VkvgPattern vkvg_pattern_create_linear(float x0, float y0, float x1, float y1);
/**
* @brief edit an existing linear gradient.
*
* @param y1 y coordinate of the end point
* @return VKVG_STATUS_SUCCESS, or VKVG_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a linear gradient.
*/
-vkvg_public
-vkvg_status_t vkvg_pattern_edit_linear(VkvgPattern pat, float x0, float y0, float x1, float y1);
+vkvg_public vkvg_status_t vkvg_pattern_edit_linear(VkvgPattern pat, float x0, float y0, float x1, float y1);
/**
* @brief get the gradient end points for a linear gradient
*
* @param y1 y coordinate of the end point
* @return VKVG_STATUS_SUCCESS, or VKVG_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a linear gradient.
*/
-vkvg_public
-vkvg_status_t vkvg_pattern_get_linear_points(VkvgPattern pat, float* x0, float* y0, float* x1, float* y1);
+vkvg_public vkvg_status_t vkvg_pattern_get_linear_points(VkvgPattern pat, float *x0, float *y0, float *x1, float *y1);
/**
* @brief create a new radial gradient.
- *
+ *
* Creates a new radial gradient between the two circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1).
* Before using the gradient pattern, a number of color stops should be defined using vkvg_pattern_add_color_stop.
*
* @param radius1 radius for the center of the end circle, the outer circle.
* @return VkvgPattern the newly created pattern to be disposed when finished by calling @ref vkvg_pattern_destroy.
*/
-vkvg_public
-VkvgPattern vkvg_pattern_create_radial (float cx0, float cy0, float radius0,
- float cx1, float cy1, float radius1);
+vkvg_public VkvgPattern vkvg_pattern_create_radial(float cx0, float cy0, float radius0, float cx1, float cy1,
+ float radius1);
/**
* @brief edit an existing radial gradient.
*
* @param radius1 radius for the center of the end circle, the outer circle.
* @return VKVG_STATUS_SUCCESS, or VKVG_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a radial gradient.
*/
-vkvg_public
-vkvg_status_t vkvg_pattern_edit_radial(VkvgPattern pat,
- float cx0, float cy0, float radius0,
- float cx1, float cy1, float radius1);
+vkvg_public vkvg_status_t vkvg_pattern_edit_radial(VkvgPattern pat, float cx0, float cy0, float radius0, float cx1,
+ float cy1, float radius1);
/**
* @brief get color stop count.
*
* @param count a valid integer pointer to old the current stop count returned.
* @return VKVG_STATUS_SUCCESS, or VKVG_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a gradient.
*/
-vkvg_public
-vkvg_status_t vkvg_pattern_get_color_stop_count (VkvgPattern pat, uint32_t* count);
+vkvg_public vkvg_status_t vkvg_pattern_get_color_stop_count(VkvgPattern pat, uint32_t *count);
/**
* @brief get color stop.
*
- * Gets the color and offset information at the given index for a gradient pattern. Values of index range from 0 to n-1 where n is the number
- * returned by @ref vkvg_pattern_get_color_stop_count().
+ * Gets the color and offset information at the given index for a gradient pattern. Values of index range from 0 to n-1
+ * where n is the number returned by @ref vkvg_pattern_get_color_stop_count().
*
* @param pat a valid pattern pointer.
* @param index index of the stop to return data for.
* @param g a valid float pointer to old the green component.
* @param b a valid float pointer to old the blue component.
* @param a a valid float pointer to old the alpha component.
- * @return VKVG_STATUS_SUCCESS, VKVG_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a gradient, VKVG_STATUS_INVALID_INDEX if index is out of bounds.
+ * @return VKVG_STATUS_SUCCESS, VKVG_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a gradient,
+ * VKVG_STATUS_INVALID_INDEX if index is out of bounds.
*/
-vkvg_public
-vkvg_status_t vkvg_pattern_get_color_stop_rgba (VkvgPattern pat, uint32_t index,
- float* offset, float* r, float* g, float* b, float* a);
+vkvg_public vkvg_status_t vkvg_pattern_get_color_stop_rgba(VkvgPattern pat, uint32_t index, float *offset, float *r,
+ float *g, float *b, float *a);
/**
* @brief dispose pattern.
- *
+ *
* When you have finished using a pattern, free its resources by calling this method.
*
* @param pat the pattern to destroy.
*/
-vkvg_public
-void vkvg_pattern_destroy (VkvgPattern pat);
+vkvg_public void vkvg_pattern_destroy(VkvgPattern pat);
/**
* @brief add colors to gradients
- *
+ *
* for each color step in the gradient, call this method and provide an absolute position between 0 and 1
* and a color.
*
* @param b the blue component of the color stop
* @param a the alpha chanel of the color stop
*/
-vkvg_public
-vkvg_status_t vkvg_pattern_add_color_stop(VkvgPattern pat, float offset, float r, float g, float b, float a);
+vkvg_public vkvg_status_t vkvg_pattern_add_color_stop(VkvgPattern pat, float offset, float r, float g, float b,
+ float a);
/**
* @brief control the extend of the pattern
- *
+ *
* control whether the pattern has to be repeated or extended when painted on a surface.
*
* @param pat the pattern to set extend for.
* @param extend one value of the @ref vkvg_extend_t enumeration.
* @return VKVG_STATUS_SUCCESS, or VKVG_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a gradient.
*/
-vkvg_public
-void vkvg_pattern_set_extend (VkvgPattern pat, vkvg_extend_t extend);
+vkvg_public void vkvg_pattern_set_extend(VkvgPattern pat, vkvg_extend_t extend);
/**
* @brief control the filtering when using this pattern on a surface.
*
* @param pat pat the pattern to set filter for.
* @param filter one value of the @ref vkvg_filter_t enumeration.
*/
-vkvg_public
-void vkvg_pattern_set_filter (VkvgPattern pat, vkvg_filter_t filter);
+vkvg_public void vkvg_pattern_set_filter(VkvgPattern pat, vkvg_filter_t filter);
/**
* @brief query the current extend value for a pa
*
* @param pat
* @return vkvg_extend_t
*/
-vkvg_public
-vkvg_extend_t vkvg_pattern_get_extend (VkvgPattern pat);
+vkvg_public vkvg_extend_t vkvg_pattern_get_extend(VkvgPattern pat);
/**
* @brief
*
* @param pat
* @return vkvg_filter_t
*/
-vkvg_public
-vkvg_filter_t vkvg_pattern_get_filter (VkvgPattern pat);
+vkvg_public vkvg_filter_t vkvg_pattern_get_filter(VkvgPattern pat);
/**
* @brief get pattern type
*
* @param pat the pattern to query
* @return vkvg_pattern_type_t
*/
-vkvg_public
-vkvg_pattern_type_t vkvg_pattern_get_type (VkvgPattern pat);
-vkvg_public
-void vkvg_pattern_set_matrix (VkvgPattern pat, const vkvg_matrix_t* matrix);
-vkvg_public
-void vkvg_pattern_get_matrix (VkvgPattern pat, vkvg_matrix_t* matrix);
+vkvg_public vkvg_pattern_type_t vkvg_pattern_get_type(VkvgPattern pat);
+vkvg_public void vkvg_pattern_set_matrix(VkvgPattern pat, const vkvg_matrix_t *matrix);
+vkvg_public void vkvg_pattern_get_matrix(VkvgPattern pat, vkvg_matrix_t *matrix);
/** @}*/
/********* EXPERIMENTAL **************/
-vkvg_public
-void vkvg_set_source_color_name (VkvgContext ctx, const char* color);
+vkvg_public void vkvg_set_source_color_name(VkvgContext ctx, const char *color);
#ifdef VKVG_RECORDING
-typedef struct _vkvg_recording_t* VkvgRecording;
+typedef struct _vkvg_recording_t *VkvgRecording;
-vkvg_public
-void vkvg_start_recording (VkvgContext ctx);
-vkvg_public
-VkvgRecording vkvg_stop_recording (VkvgContext ctx);
-vkvg_public
-void vkvg_replay (VkvgContext ctx, VkvgRecording rec);
-vkvg_public
-void vkvg_replay_command (VkvgContext ctx, VkvgRecording rec, uint32_t cmdIndex);
-vkvg_public
-void vkvg_recording_get_command (VkvgRecording rec, uint32_t cmdIndex, uint32_t* cmd, void** dataOffset);
-vkvg_public
-uint32_t vkvg_recording_get_count(VkvgRecording rec);
-vkvg_public
-void* vkvg_recording_get_data (VkvgRecording rec);
-vkvg_public
-void vkvg_recording_destroy (VkvgRecording rec);
+vkvg_public void vkvg_start_recording(VkvgContext ctx);
+vkvg_public VkvgRecording vkvg_stop_recording(VkvgContext ctx);
+vkvg_public void vkvg_replay(VkvgContext ctx, VkvgRecording rec);
+vkvg_public void vkvg_replay_command(VkvgContext ctx, VkvgRecording rec, uint32_t cmdIndex);
+vkvg_public void vkvg_recording_get_command(VkvgRecording rec, uint32_t cmdIndex, uint32_t *cmd, void **dataOffset);
+vkvg_public uint32_t vkvg_recording_get_count(VkvgRecording rec);
+vkvg_public void *vkvg_recording_get_data(VkvgRecording rec);
+vkvg_public void vkvg_recording_destroy(VkvgRecording rec);
/*************************************/
#endif
#define _CRT_SECURE_NO_WARNINGS
-int directoryExists (const char* path) {
+int directoryExists(const char *path) {
#if defined(_WIN32) || defined(_WIN64)
#elif __APPLE__
#elif __unix__
- struct stat st = {0};
- return stat(path, &st)+1;
+ struct stat st = {0};
+ return stat(path, &st) + 1;
#else
- return -1;
+ return -1;
#endif
}
-const char* getUserDir () {
+const char *getUserDir() {
#if defined(_WIN32) || defined(_WIN64)
- return getenv("HOME");
+ return getenv("HOME");
#elif __APPLE__
#elif __unix__
- struct passwd *pw = getpwuid(getuid());
- return pw->pw_dir;
+ struct passwd *pw = getpwuid(getuid());
+ return pw->pw_dir;
#endif
}
#include <unistd.h>
void handler(int sig) {
- void *array[100];
- size_t size;
+ void *array[100];
+ size_t size;
- // get void*'s for all entries on the stack
- size = backtrace(array, 100);
+ // get void*'s for all entries on the stack
+ size = backtrace(array, 100);
- // print out all the frames to stderr
- fprintf(stderr, "Error: signal %d:\n", sig);
- backtrace_symbols_fd(array, size, STDERR_FILENO);
- exit(1);
+ // print out all the frames to stderr
+ fprintf(stderr, "Error: signal %d:\n", sig);
+ backtrace_symbols_fd(array, size, STDERR_FILENO);
+ exit(1);
}
-void _linux_register_error_handler () {
- signal(SIGSEGV, handler); // install our handler
- signal(SIGABRT, handler); // install our handler
+void _linux_register_error_handler() {
+ signal(SIGSEGV, handler); // install our handler
+ signal(SIGABRT, handler); // install our handler
}
#endif
#ifndef CROSS_OS_H
#define CROSS_OS_H
-//cross platform os helpers
+// cross platform os helpers
#if defined(_WIN32) || defined(_WIN64)
- //disable warning on iostream functions on windows
- #define _CRT_SECURE_NO_WARNINGS
- #include "windows.h"
- #if defined(_WIN64)
- #ifndef isnan
- #define isnan _isnanf
- #endif
- #endif
- #define vkvg_inline __forceinline
- #define disable_warning (warn)
- #define reset_warning (warn)
+// disable warning on iostream functions on windows
+#define _CRT_SECURE_NO_WARNINGS
+#include "windows.h"
+#if defined(_WIN64)
+#ifndef isnan
+#define isnan _isnanf
+#endif
+#endif
+#define vkvg_inline __forceinline
+#define disable_warning (warn)
+#define reset_warning (warn)
#elif __APPLE__
- #include <math.h>
- #define vkvg_inline static
- #define disable_warning (warn)
- #define reset_warning (warn)
+#include <math.h>
+#define vkvg_inline static
+#define disable_warning (warn)
+#define reset_warning (warn)
#elif __unix__
- #include <unistd.h>
- #include <sys/types.h>
- #include <pwd.h>
- #define vkvg_inline static inline __attribute((always_inline))
- #define disable_warning (warn) #pragma GCC diagnostic ignored "-W"#warn
- #define reset_warning (warn) #pragma GCC diagnostic warning "-W"#warn
- #if __linux__
- void _linux_register_error_handler ();
- #endif
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#define vkvg_inline static inline __attribute((always_inline))
+#define disable_warning (warn) #pragma GCC diagnostic ignored "-W" #warn
+#define reset_warning (warn) #pragma GCC diagnostic warning "-W" #warn
+#if __linux__
+void _linux_register_error_handler();
+#endif
#endif
-const char* getUserDir ();
+const char *getUserDir();
#endif // CROSS_OS_H
/* Platform specific includes */
#if defined(_TTHREAD_POSIX_)
- #include <signal.h>
- #include <sched.h>
- #include <unistd.h>
- #include <sys/time.h>
- #include <errno.h>
+#include <signal.h>
+#include <sched.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <errno.h>
#elif defined(_TTHREAD_WIN32_)
- #include <process.h>
- #include <sys/timeb.h>
+#include <process.h>
+#include <sys/timeb.h>
#endif
/* Standard, good-to-have defines */
#ifndef NULL
- #define NULL (void*)0
+#define NULL (void *)0
#endif
#ifndef TRUE
- #define TRUE 1
+#define TRUE 1
#endif
#ifndef FALSE
- #define FALSE 0
+#define FALSE 0
#endif
-int mtx_init(mtx_t *mtx, int type)
-{
+int mtx_init(mtx_t *mtx, int type) {
#if defined(_TTHREAD_WIN32_)
- mtx->mAlreadyLocked = FALSE;
- mtx->mRecursive = type & mtx_recursive;
- InitializeCriticalSection(&mtx->mHandle);
- return thrd_success;
+ mtx->mAlreadyLocked = FALSE;
+ mtx->mRecursive = type & mtx_recursive;
+ InitializeCriticalSection(&mtx->mHandle);
+ return thrd_success;
#else
- int ret;
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- if (type & mtx_recursive)
- {
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- }
- ret = pthread_mutex_init(mtx, &attr);
- pthread_mutexattr_destroy(&attr);
- return ret == 0 ? thrd_success : thrd_error;
+ int ret;
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ if (type & mtx_recursive) {
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ }
+ ret = pthread_mutex_init(mtx, &attr);
+ pthread_mutexattr_destroy(&attr);
+ return ret == 0 ? thrd_success : thrd_error;
#endif
}
-void mtx_destroy(mtx_t *mtx)
-{
+void mtx_destroy(mtx_t *mtx) {
#if defined(_TTHREAD_WIN32_)
- DeleteCriticalSection(&mtx->mHandle);
+ DeleteCriticalSection(&mtx->mHandle);
#else
- pthread_mutex_destroy(mtx);
+ pthread_mutex_destroy(mtx);
#endif
}
-int mtx_lock(mtx_t *mtx)
-{
+int mtx_lock(mtx_t *mtx) {
#if defined(_TTHREAD_WIN32_)
- EnterCriticalSection(&mtx->mHandle);
- if (!mtx->mRecursive)
- {
- while(mtx->mAlreadyLocked) Sleep(1000); /* Simulate deadlock... */
- mtx->mAlreadyLocked = TRUE;
- }
- return thrd_success;
+ EnterCriticalSection(&mtx->mHandle);
+ if (!mtx->mRecursive) {
+ while (mtx->mAlreadyLocked)
+ Sleep(1000); /* Simulate deadlock... */
+ mtx->mAlreadyLocked = TRUE;
+ }
+ return thrd_success;
#else
- return pthread_mutex_lock(mtx) == 0 ? thrd_success : thrd_error;
+ return pthread_mutex_lock(mtx) == 0 ? thrd_success : thrd_error;
#endif
}
-int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
-{
- /* FIXME! */
- (void)mtx;
- (void)ts;
- return thrd_error;
+int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) {
+ /* FIXME! */
+ (void)mtx;
+ (void)ts;
+ return thrd_error;
}
-int mtx_trylock(mtx_t *mtx)
-{
+int mtx_trylock(mtx_t *mtx) {
#if defined(_TTHREAD_WIN32_)
- int ret = TryEnterCriticalSection(&mtx->mHandle) ? thrd_success : thrd_busy;
- if ((!mtx->mRecursive) && (ret == thrd_success) && mtx->mAlreadyLocked)
- {
- LeaveCriticalSection(&mtx->mHandle);
- ret = thrd_busy;
- }
- return ret;
+ int ret = TryEnterCriticalSection(&mtx->mHandle) ? thrd_success : thrd_busy;
+ if ((!mtx->mRecursive) && (ret == thrd_success) && mtx->mAlreadyLocked) {
+ LeaveCriticalSection(&mtx->mHandle);
+ ret = thrd_busy;
+ }
+ return ret;
#else
- return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy;
+ return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy;
#endif
}
-int mtx_unlock(mtx_t *mtx)
-{
+int mtx_unlock(mtx_t *mtx) {
#if defined(_TTHREAD_WIN32_)
- mtx->mAlreadyLocked = FALSE;
- LeaveCriticalSection(&mtx->mHandle);
- return thrd_success;
+ mtx->mAlreadyLocked = FALSE;
+ LeaveCriticalSection(&mtx->mHandle);
+ return thrd_success;
#else
- return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;;
+ return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;
+ ;
#endif
}
#define _CONDITION_EVENT_ALL 1
#endif
-int cnd_init(cnd_t *cond)
-{
+int cnd_init(cnd_t *cond) {
#if defined(_TTHREAD_WIN32_)
- cond->mWaitersCount = 0;
+ cond->mWaitersCount = 0;
- /* Init critical section */
- InitializeCriticalSection(&cond->mWaitersCountLock);
+ /* Init critical section */
+ InitializeCriticalSection(&cond->mWaitersCountLock);
- /* Init events */
- cond->mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (cond->mEvents[_CONDITION_EVENT_ONE] == NULL)
- {
- cond->mEvents[_CONDITION_EVENT_ALL] = NULL;
- return thrd_error;
- }
- cond->mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (cond->mEvents[_CONDITION_EVENT_ALL] == NULL)
- {
- CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
- cond->mEvents[_CONDITION_EVENT_ONE] = NULL;
- return thrd_error;
- }
+ /* Init events */
+ cond->mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (cond->mEvents[_CONDITION_EVENT_ONE] == NULL) {
+ cond->mEvents[_CONDITION_EVENT_ALL] = NULL;
+ return thrd_error;
+ }
+ cond->mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (cond->mEvents[_CONDITION_EVENT_ALL] == NULL) {
+ CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
+ cond->mEvents[_CONDITION_EVENT_ONE] = NULL;
+ return thrd_error;
+ }
- return thrd_success;
+ return thrd_success;
#else
- return pthread_cond_init(cond, NULL) == 0 ? thrd_success : thrd_error;
+ return pthread_cond_init(cond, NULL) == 0 ? thrd_success : thrd_error;
#endif
}
-void cnd_destroy(cnd_t *cond)
-{
+void cnd_destroy(cnd_t *cond) {
#if defined(_TTHREAD_WIN32_)
- if (cond->mEvents[_CONDITION_EVENT_ONE] != NULL)
- {
- CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
- }
- if (cond->mEvents[_CONDITION_EVENT_ALL] != NULL)
- {
- CloseHandle(cond->mEvents[_CONDITION_EVENT_ALL]);
- }
- DeleteCriticalSection(&cond->mWaitersCountLock);
+ if (cond->mEvents[_CONDITION_EVENT_ONE] != NULL) {
+ CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
+ }
+ if (cond->mEvents[_CONDITION_EVENT_ALL] != NULL) {
+ CloseHandle(cond->mEvents[_CONDITION_EVENT_ALL]);
+ }
+ DeleteCriticalSection(&cond->mWaitersCountLock);
#else
- pthread_cond_destroy(cond);
+ pthread_cond_destroy(cond);
#endif
}
-int cnd_signal(cnd_t *cond)
-{
+int cnd_signal(cnd_t *cond) {
#if defined(_TTHREAD_WIN32_)
- int haveWaiters;
-
- /* Are there any waiters? */
- EnterCriticalSection(&cond->mWaitersCountLock);
- haveWaiters = (cond->mWaitersCount > 0);
- LeaveCriticalSection(&cond->mWaitersCountLock);
-
- /* If we have any waiting threads, send them a signal */
- if(haveWaiters)
- {
- if (SetEvent(cond->mEvents[_CONDITION_EVENT_ONE]) == 0)
- {
- return thrd_error;
+ int haveWaiters;
+
+ /* Are there any waiters? */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ haveWaiters = (cond->mWaitersCount > 0);
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* If we have any waiting threads, send them a signal */
+ if (haveWaiters) {
+ if (SetEvent(cond->mEvents[_CONDITION_EVENT_ONE]) == 0) {
+ return thrd_error;
+ }
}
- }
- return thrd_success;
+ return thrd_success;
#else
- return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
+ return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
#endif
}
-int cnd_broadcast(cnd_t *cond)
-{
+int cnd_broadcast(cnd_t *cond) {
#if defined(_TTHREAD_WIN32_)
- int haveWaiters;
-
- /* Are there any waiters? */
- EnterCriticalSection(&cond->mWaitersCountLock);
- haveWaiters = (cond->mWaitersCount > 0);
- LeaveCriticalSection(&cond->mWaitersCountLock);
-
- /* If we have any waiting threads, send them a signal */
- if(haveWaiters)
- {
- if (SetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
- {
- return thrd_error;
+ int haveWaiters;
+
+ /* Are there any waiters? */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ haveWaiters = (cond->mWaitersCount > 0);
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* If we have any waiting threads, send them a signal */
+ if (haveWaiters) {
+ if (SetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0) {
+ return thrd_error;
+ }
}
- }
- return thrd_success;
+ return thrd_success;
#else
- return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
+ return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
#endif
}
#if defined(_TTHREAD_WIN32_)
-static int _cnd_timedwait_win32(cnd_t *cond, mtx_t *mtx, DWORD timeout)
-{
- int result, lastWaiter;
-
- /* Increment number of waiters */
- EnterCriticalSection(&cond->mWaitersCountLock);
- ++ cond->mWaitersCount;
- LeaveCriticalSection(&cond->mWaitersCountLock);
-
- /* Release the mutex while waiting for the condition (will decrease
- the number of waiters when done)... */
- mtx_unlock(mtx);
-
- /* Wait for either event to become signaled due to cnd_signal() or
- cnd_broadcast() being called */
- result = WaitForMultipleObjects(2, cond->mEvents, FALSE, timeout);
- if (result == WAIT_TIMEOUT)
- {
- return thrd_timeout;
- }
- else if (result == (int)WAIT_FAILED)
- {
- return thrd_error;
- }
-
- /* Check if we are the last waiter */
- EnterCriticalSection(&cond->mWaitersCountLock);
- -- cond->mWaitersCount;
- lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) &&
- (cond->mWaitersCount == 0);
- LeaveCriticalSection(&cond->mWaitersCountLock);
-
- /* If we are the last waiter to be notified to stop waiting, reset the event */
- if (lastWaiter)
- {
- if (ResetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
- {
- return thrd_error;
+static int _cnd_timedwait_win32(cnd_t *cond, mtx_t *mtx, DWORD timeout) {
+ int result, lastWaiter;
+
+ /* Increment number of waiters */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ ++cond->mWaitersCount;
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* Release the mutex while waiting for the condition (will decrease
+ the number of waiters when done)... */
+ mtx_unlock(mtx);
+
+ /* Wait for either event to become signaled due to cnd_signal() or
+ cnd_broadcast() being called */
+ result = WaitForMultipleObjects(2, cond->mEvents, FALSE, timeout);
+ if (result == WAIT_TIMEOUT) {
+ return thrd_timeout;
+ } else if (result == (int)WAIT_FAILED) {
+ return thrd_error;
+ }
+
+ /* Check if we are the last waiter */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ --cond->mWaitersCount;
+ lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) && (cond->mWaitersCount == 0);
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* If we are the last waiter to be notified to stop waiting, reset the event */
+ if (lastWaiter) {
+ if (ResetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0) {
+ return thrd_error;
+ }
}
- }
- /* Re-acquire the mutex */
- mtx_lock(mtx);
+ /* Re-acquire the mutex */
+ mtx_lock(mtx);
- return thrd_success;
+ return thrd_success;
}
#endif
-int cnd_wait(cnd_t *cond, mtx_t *mtx)
-{
+int cnd_wait(cnd_t *cond, mtx_t *mtx) {
#if defined(_TTHREAD_WIN32_)
- return _cnd_timedwait_win32(cond, mtx, INFINITE);
+ return _cnd_timedwait_win32(cond, mtx, INFINITE);
#else
- return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error;
+ return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error;
#endif
}
-int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
-{
+int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts) {
#if defined(_TTHREAD_WIN32_)
- struct timespec now;
- if (clock_gettime(CLOCK_REALTIME, &now) == 0)
- {
- DWORD delta = (DWORD) ((ts->tv_sec - now.tv_sec) * 1000 +
- (ts->tv_nsec - now.tv_nsec + 500000) / 1000000);
- return _cnd_timedwait_win32(cond, mtx, delta);
- }
- else
- return thrd_error;
+ struct timespec now;
+ if (clock_gettime(CLOCK_REALTIME, &now) == 0) {
+ DWORD delta = (DWORD)((ts->tv_sec - now.tv_sec) * 1000 + (ts->tv_nsec - now.tv_nsec + 500000) / 1000000);
+ return _cnd_timedwait_win32(cond, mtx, delta);
+ } else
+ return thrd_error;
#else
- int ret;
- ret = pthread_cond_timedwait(cond, mtx, ts);
- if (ret == ETIMEDOUT)
- {
- return thrd_timeout;
- }
- return ret == 0 ? thrd_success : thrd_error;
+ int ret;
+ ret = pthread_cond_timedwait(cond, mtx, ts);
+ if (ret == ETIMEDOUT) {
+ return thrd_timeout;
+ }
+ return ret == 0 ? thrd_success : thrd_error;
#endif
}
-
/** Information to pass to the new thread (what to run). */
typedef struct {
- thrd_start_t mFunction; /**< Pointer to the function to be executed. */
- void * mArg; /**< Function argument for the thread function. */
+ thrd_start_t mFunction; /**< Pointer to the function to be executed. */
+ void *mArg; /**< Function argument for the thread function. */
} _thread_start_info;
/* Thread wrapper function. */
#if defined(_TTHREAD_WIN32_)
-static unsigned WINAPI _thrd_wrapper_function(void * aArg)
+static unsigned WINAPI _thrd_wrapper_function(void *aArg)
#elif defined(_TTHREAD_POSIX_)
-static void * _thrd_wrapper_function(void * aArg)
+static void *_thrd_wrapper_function(void *aArg)
#endif
{
- thrd_start_t fun;
- void *arg;
- int res;
+ thrd_start_t fun;
+ void *arg;
+ int res;
#if defined(_TTHREAD_POSIX_)
- void *pres;
+ void *pres;
#endif
- /* Get thread startup information */
- _thread_start_info *ti = (_thread_start_info *) aArg;
- fun = ti->mFunction;
- arg = ti->mArg;
+ /* Get thread startup information */
+ _thread_start_info *ti = (_thread_start_info *)aArg;
+ fun = ti->mFunction;
+ arg = ti->mArg;
- /* The thread is responsible for freeing the startup information */
- free((void *)ti);
+ /* The thread is responsible for freeing the startup information */
+ free((void *)ti);
- /* Call the actual client thread function */
- res = fun(arg);
+ /* Call the actual client thread function */
+ res = fun(arg);
#if defined(_TTHREAD_WIN32_)
- return res;
+ return res;
#else
- pres = malloc(sizeof(int));
- if (pres != NULL)
- {
- *(int*)pres = res;
- }
- return pres;
+ pres = malloc(sizeof(int));
+ if (pres != NULL) {
+ *(int *)pres = res;
+ }
+ return pres;
#endif
}
-int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
-{
- /* Fill out the thread startup information (passed to the thread wrapper,
- which will eventually free it) */
- _thread_start_info* ti = (_thread_start_info*)malloc(sizeof(_thread_start_info));
- if (ti == NULL)
- {
- return thrd_nomem;
- }
- ti->mFunction = func;
- ti->mArg = arg;
-
- /* Create the thread */
+int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) {
+ /* Fill out the thread startup information (passed to the thread wrapper,
+ which will eventually free it) */
+ _thread_start_info *ti = (_thread_start_info *)malloc(sizeof(_thread_start_info));
+ if (ti == NULL) {
+ return thrd_nomem;
+ }
+ ti->mFunction = func;
+ ti->mArg = arg;
+
+ /* Create the thread */
#if defined(_TTHREAD_WIN32_)
- *thr = (HANDLE)_beginthreadex(NULL, 0, _thrd_wrapper_function, (void *)ti, 0, NULL);
+ *thr = (HANDLE)_beginthreadex(NULL, 0, _thrd_wrapper_function, (void *)ti, 0, NULL);
#elif defined(_TTHREAD_POSIX_)
- if(pthread_create(thr, NULL, _thrd_wrapper_function, (void *)ti) != 0)
- {
- *thr = 0;
- }
+ if (pthread_create(thr, NULL, _thrd_wrapper_function, (void *)ti) != 0) {
+ *thr = 0;
+ }
#endif
- /* Did we fail to create the thread? */
- if(!*thr)
- {
- free(ti);
- return thrd_error;
- }
+ /* Did we fail to create the thread? */
+ if (!*thr) {
+ free(ti);
+ return thrd_error;
+ }
- return thrd_success;
+ return thrd_success;
}
-thrd_t thrd_current(void)
-{
+thrd_t thrd_current(void) {
#if defined(_TTHREAD_WIN32_)
- return GetCurrentThread();
+ return GetCurrentThread();
#else
- return pthread_self();
+ return pthread_self();
#endif
}
-int thrd_detach(thrd_t thr)
-{
- /* FIXME! */
- (void)thr;
- return thrd_error;
+int thrd_detach(thrd_t thr) {
+ /* FIXME! */
+ (void)thr;
+ return thrd_error;
}
-int thrd_equal(thrd_t thr0, thrd_t thr1)
-{
+int thrd_equal(thrd_t thr0, thrd_t thr1) {
#if defined(_TTHREAD_WIN32_)
- return thr0 == thr1;
+ return thr0 == thr1;
#else
- return pthread_equal(thr0, thr1);
+ return pthread_equal(thr0, thr1);
#endif
}
-void thrd_exit(int res)
-{
+void thrd_exit(int res) {
#if defined(_TTHREAD_WIN32_)
- ExitThread(res);
+ ExitThread(res);
#else
- void *pres = malloc(sizeof(int));
- if (pres != NULL)
- {
- *(int*)pres = res;
- }
- pthread_exit(pres);
+ void *pres = malloc(sizeof(int));
+ if (pres != NULL) {
+ *(int *)pres = res;
+ }
+ pthread_exit(pres);
#endif
}
-int thrd_join(thrd_t thr, int *res)
-{
+int thrd_join(thrd_t thr, int *res) {
#if defined(_TTHREAD_WIN32_)
- if (WaitForSingleObject(thr, INFINITE) == WAIT_FAILED)
- {
- return thrd_error;
- }
- if (res != NULL)
- {
- DWORD dwRes;
- GetExitCodeThread(thr, &dwRes);
- *res = dwRes;
- }
+ if (WaitForSingleObject(thr, INFINITE) == WAIT_FAILED) {
+ return thrd_error;
+ }
+ if (res != NULL) {
+ DWORD dwRes;
+ GetExitCodeThread(thr, &dwRes);
+ *res = dwRes;
+ }
#elif defined(_TTHREAD_POSIX_)
- void *pres;
- int ires = 0;
- if (pthread_join(thr, &pres) != 0)
- {
- return thrd_error;
- }
- if (pres != NULL)
- {
- ires = *(int*)pres;
- free(pres);
- }
- if (res != NULL)
- {
- *res = ires;
- }
-#endif
- return thrd_success;
+ void *pres;
+ int ires = 0;
+ if (pthread_join(thr, &pres) != 0) {
+ return thrd_error;
+ }
+ if (pres != NULL) {
+ ires = *(int *)pres;
+ free(pres);
+ }
+ if (res != NULL) {
+ *res = ires;
+ }
+#endif
+ return thrd_success;
}
-int thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
-{
- struct timespec now;
+int thrd_sleep(const struct timespec *time_point, struct timespec *remaining) {
+ struct timespec now;
#if defined(_TTHREAD_WIN32_)
- DWORD delta;
+ DWORD delta;
#else
- long delta;
+ long delta;
#endif
- /* Get the current time */
- if (clock_gettime(CLOCK_REALTIME, &now) != 0)
- return -2; // FIXME: Some specific error code?
+ /* Get the current time */
+ if (clock_gettime(CLOCK_REALTIME, &now) != 0)
+ return -2; // FIXME: Some specific error code?
#if defined(_TTHREAD_WIN32_)
- /* Delta in milliseconds */
- delta = (DWORD) ((time_point->tv_sec - now.tv_sec) * 1000 +
- (time_point->tv_nsec - now.tv_nsec + 500000) / 1000000);
- if (delta > 0)
- {
- Sleep(delta);
- }
+ /* Delta in milliseconds */
+ delta = (DWORD)((time_point->tv_sec - now.tv_sec) * 1000 + (time_point->tv_nsec - now.tv_nsec + 500000) / 1000000);
+ if (delta > 0) {
+ Sleep(delta);
+ }
#else
- /* Delta in microseconds */
- delta = (time_point->tv_sec - now.tv_sec) * 1000000L +
- (time_point->tv_nsec - now.tv_nsec + 500L) / 1000L;
-
- /* On some systems, the usleep argument must be < 1000000 */
- while (delta > 999999L)
- {
- usleep(999999);
- delta -= 999999L;
- }
- if (delta > 0L)
- {
- usleep((useconds_t)delta);
- }
-#endif
-
- /* We don't support waking up prematurely (yet) */
- if (remaining)
- {
- remaining->tv_sec = 0;
- remaining->tv_nsec = 0;
- }
- return 0;
+ /* Delta in microseconds */
+ delta = (time_point->tv_sec - now.tv_sec) * 1000000L + (time_point->tv_nsec - now.tv_nsec + 500L) / 1000L;
+
+ /* On some systems, the usleep argument must be < 1000000 */
+ while (delta > 999999L) {
+ usleep(999999);
+ delta -= 999999L;
+ }
+ if (delta > 0L) {
+ usleep((useconds_t)delta);
+ }
+#endif
+
+ /* We don't support waking up prematurely (yet) */
+ if (remaining) {
+ remaining->tv_sec = 0;
+ remaining->tv_nsec = 0;
+ }
+ return 0;
}
-void thrd_yield(void)
-{
+void thrd_yield(void) {
#if defined(_TTHREAD_WIN32_)
- Sleep(0);
+ Sleep(0);
#else
- sched_yield();
+ sched_yield();
#endif
}
-int tss_create(tss_t *key, tss_dtor_t dtor)
-{
+int tss_create(tss_t *key, tss_dtor_t dtor) {
#if defined(_TTHREAD_WIN32_)
- /* FIXME: The destructor function is not supported yet... */
- if (dtor != NULL)
- {
- return thrd_error;
- }
- *key = TlsAlloc();
- if (*key == TLS_OUT_OF_INDEXES)
- {
- return thrd_error;
- }
+ /* FIXME: The destructor function is not supported yet... */
+ if (dtor != NULL) {
+ return thrd_error;
+ }
+ *key = TlsAlloc();
+ if (*key == TLS_OUT_OF_INDEXES) {
+ return thrd_error;
+ }
#else
- if (pthread_key_create(key, dtor) != 0)
- {
- return thrd_error;
- }
+ if (pthread_key_create(key, dtor) != 0) {
+ return thrd_error;
+ }
#endif
- return thrd_success;
+ return thrd_success;
}
-void tss_delete(tss_t key)
-{
+void tss_delete(tss_t key) {
#if defined(_TTHREAD_WIN32_)
- TlsFree(key);
+ TlsFree(key);
#else
- pthread_key_delete(key);
+ pthread_key_delete(key);
#endif
}
-void *tss_get(tss_t key)
-{
+void *tss_get(tss_t key) {
#if defined(_TTHREAD_WIN32_)
- return TlsGetValue(key);
+ return TlsGetValue(key);
#else
- return pthread_getspecific(key);
+ return pthread_getspecific(key);
#endif
}
-int tss_set(tss_t key, void *val)
-{
+int tss_set(tss_t key, void *val) {
#if defined(_TTHREAD_WIN32_)
- if (TlsSetValue(key, val) == 0)
- {
- return thrd_error;
- }
+ if (TlsSetValue(key, val) == 0) {
+ return thrd_error;
+ }
#else
- if (pthread_setspecific(key, val) != 0)
- {
- return thrd_error;
- }
+ if (pthread_setspecific(key, val) != 0) {
+ return thrd_error;
+ }
#endif
- return thrd_success;
+ return thrd_success;
}
#if defined(_TTHREAD_EMULATE_CLOCK_GETTIME_)
-int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts)
-{
+int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts) {
#if defined(_TTHREAD_WIN32_)
- struct _timeb tb;
- _ftime(&tb);
- ts->tv_sec = (time_t)tb.time;
- ts->tv_nsec = 1000000L * (long)tb.millitm;
+ struct _timeb tb;
+ _ftime(&tb);
+ ts->tv_sec = (time_t)tb.time;
+ ts->tv_nsec = 1000000L * (long)tb.millitm;
#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- ts->tv_sec = (time_t)tv.tv_sec;
- ts->tv_nsec = 1000L * (long)tv.tv_usec;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ ts->tv_sec = (time_t)tv.tv_sec;
+ ts->tv_nsec = 1000L * (long)tv.tv_usec;
#endif
- return 0;
+ return 0;
}
#endif // _TTHREAD_EMULATE_CLOCK_GETTIME_
-
#define _TINYCTHREAD_H_
/**
-* @file
-* @mainpage TinyCThread API Reference
-*
-* @section intro_sec Introduction
-* TinyCThread is a minimal, portable implementation of basic threading
-* classes for C.
-*
-* They closely mimic the functionality and naming of the C11 standard, and
-* should be easily replaceable with the corresponding standard variants.
-*
-* @section port_sec Portability
-* The Win32 variant uses the native Win32 API for implementing the thread
-* classes, while for other systems, the POSIX threads API (pthread) is used.
-*
-* @section misc_sec Miscellaneous
-* The following special keywords are available: #_Thread_local.
-*
-* For more detailed information, browse the different sections of this
-* documentation. A good place to start is:
-* tinycthread.h.
-*/
+ * @file
+ * @mainpage TinyCThread API Reference
+ *
+ * @section intro_sec Introduction
+ * TinyCThread is a minimal, portable implementation of basic threading
+ * classes for C.
+ *
+ * They closely mimic the functionality and naming of the C11 standard, and
+ * should be easily replaceable with the corresponding standard variants.
+ *
+ * @section port_sec Portability
+ * The Win32 variant uses the native Win32 API for implementing the thread
+ * classes, while for other systems, the POSIX threads API (pthread) is used.
+ *
+ * @section misc_sec Miscellaneous
+ * The following special keywords are available: #_Thread_local.
+ *
+ * For more detailed information, browse the different sections of this
+ * documentation. A good place to start is:
+ * tinycthread.h.
+ */
/* Which platform are we on? */
#if !defined(_TTHREAD_PLATFORM_DEFINED_)
- #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
- #define _TTHREAD_WIN32_
- #else
- #define _TTHREAD_POSIX_
- #endif
- #define _TTHREAD_PLATFORM_DEFINED_
+#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
+#define _TTHREAD_WIN32_
+#else
+#define _TTHREAD_POSIX_
+#endif
+#define _TTHREAD_PLATFORM_DEFINED_
#endif
/* Activate some POSIX functionality (e.g. clock_gettime and recursive mutexes) */
#if defined(_TTHREAD_POSIX_)
- #undef _FEATURES_H
- #if !defined(_GNU_SOURCE)
- #define _GNU_SOURCE
- #endif
- #if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L)
- #undef _POSIX_C_SOURCE
- #define _POSIX_C_SOURCE 199309L
- #endif
- #if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500)
- #undef _XOPEN_SOURCE
- #define _XOPEN_SOURCE 500
- #endif
+#undef _FEATURES_H
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE
+#endif
+#if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L)
+#undef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 199309L
+#endif
+#if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500)
+#undef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 500
+#endif
#endif
/* Generic includes */
/* Platform specific includes */
#if defined(_TTHREAD_POSIX_)
- #include <sys/time.h>
- #include <pthread.h>
+#include <sys/time.h>
+#include <pthread.h>
#elif defined(_TTHREAD_WIN32_)
- #ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN
- #define __UNDEF_LEAN_AND_MEAN
- #endif
- #include <windows.h>
- #ifdef __UNDEF_LEAN_AND_MEAN
- #undef WIN32_LEAN_AND_MEAN
- #undef __UNDEF_LEAN_AND_MEAN
- #endif
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#define __UNDEF_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#ifdef __UNDEF_LEAN_AND_MEAN
+#undef WIN32_LEAN_AND_MEAN
+#undef __UNDEF_LEAN_AND_MEAN
+#endif
#endif
/* Workaround for missing TIME_UTC: If time.h doesn't provide TIME_UTC,
the only other supported time specifier: CLOCK_REALTIME (and if that fails,
we're probably emulating clock_gettime anyway, so anything goes). */
#ifndef TIME_UTC
- #ifdef CLOCK_REALTIME
- #define TIME_UTC CLOCK_REALTIME
- #else
- #define TIME_UTC 0
- #endif
+#ifdef CLOCK_REALTIME
+#define TIME_UTC CLOCK_REALTIME
+#else
+#define TIME_UTC 0
+#endif
#endif
/* Workaround for missing clock_gettime (most Windows compilers, afaik) */
/* Emulate struct timespec */
#if defined(_TTHREAD_WIN32_)
struct _ttherad_timespec {
- time_t tv_sec;
- long tv_nsec;
+ time_t tv_sec;
+ long tv_nsec;
};
#define timespec _ttherad_timespec
#endif
int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
#define clock_gettime _tthread_clock_gettime
#ifndef CLOCK_REALTIME
- #define CLOCK_REALTIME 0
+#define CLOCK_REALTIME 0
#endif
#endif
-
/** TinyCThread version (major number). */
#define TINYCTHREAD_VERSION_MAJOR 1
/** TinyCThread version (minor number). */
#define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR)
/**
-* @def _Thread_local
-* Thread local storage keyword.
-* A variable that is declared with the @c _Thread_local keyword makes the
-* value of the variable local to each thread (known as thread-local storage,
-* or TLS). Example usage:
-* @code
-* // This variable is local to each thread.
-* _Thread_local int variable;
-* @endcode
-* @note The @c _Thread_local keyword is a macro that maps to the corresponding
-* compiler directive (e.g. @c __declspec(thread)).
-* @note This directive is currently not supported on Mac OS X (it will give
-* a compiler error), since compile-time TLS is not supported in the Mac OS X
-* executable format. Also, some older versions of MinGW (before GCC 4.x) do
-* not support this directive.
-* @hideinitializer
-*/
+ * @def _Thread_local
+ * Thread local storage keyword.
+ * A variable that is declared with the @c _Thread_local keyword makes the
+ * value of the variable local to each thread (known as thread-local storage,
+ * or TLS). Example usage:
+ * @code
+ * // This variable is local to each thread.
+ * _Thread_local int variable;
+ * @endcode
+ * @note The @c _Thread_local keyword is a macro that maps to the corresponding
+ * compiler directive (e.g. @c __declspec(thread)).
+ * @note This directive is currently not supported on Mac OS X (it will give
+ * a compiler error), since compile-time TLS is not supported in the Mac OS X
+ * executable format. Also, some older versions of MinGW (before GCC 4.x) do
+ * not support this directive.
+ * @hideinitializer
+ */
/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 */
#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
- #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
- #define _Thread_local __thread
- #else
- #define _Thread_local __declspec(thread)
- #endif
+#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+#define _Thread_local __thread
+#else
+#define _Thread_local __declspec(thread)
+#endif
#endif
/* Macros */
#define TSS_DTOR_ITERATIONS 0
/* Function return values */
-#define thrd_error 0 /**< The requested operation failed */
-#define thrd_success 1 /**< The requested operation succeeded */
-#define thrd_timeout 2 /**< The time specified in the call was reached without acquiring the requested resource */
-#define thrd_busy 3 /**< The requested operation failed because a tesource requested by a test and return function is already in use */
-#define thrd_nomem 4 /**< The requested operation failed because it was unable to allocate memory */
+#define thrd_error 0 /**< The requested operation failed */
+#define thrd_success 1 /**< The requested operation succeeded */
+#define thrd_timeout 2 /**< The time specified in the call was reached without acquiring the requested resource */
+#define thrd_busy \
+ 3 /**< The requested operation failed because a tesource requested by a test and return function is already in use \
+ */
+#define thrd_nomem 4 /**< The requested operation failed because it was unable to allocate memory */
/* Mutex types */
#define mtx_plain 1
/* Mutex */
#if defined(_TTHREAD_WIN32_)
typedef struct {
- CRITICAL_SECTION mHandle; /* Critical section handle */
- int mAlreadyLocked; /* TRUE if the mutex is already locked */
- int mRecursive; /* TRUE if the mutex is recursive */
+ CRITICAL_SECTION mHandle; /* Critical section handle */
+ int mAlreadyLocked; /* TRUE if the mutex is already locked */
+ int mRecursive; /* TRUE if the mutex is recursive */
} mtx_t;
#else
typedef pthread_mutex_t mtx_t;
#endif
/** Create a mutex object.
-* @param mtx A mutex object.
-* @param type Bit-mask that must have one of the following six values:
-* @li @c mtx_plain for a simple non-recursive mutex
-* @li @c mtx_timed for a non-recursive mutex that supports timeout
-* @li @c mtx_try for a non-recursive mutex that supports test and return
-* @li @c mtx_plain | @c mtx_recursive (same as @c mtx_plain, but recursive)
-* @li @c mtx_timed | @c mtx_recursive (same as @c mtx_timed, but recursive)
-* @li @c mtx_try | @c mtx_recursive (same as @c mtx_try, but recursive)
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * @param mtx A mutex object.
+ * @param type Bit-mask that must have one of the following six values:
+ * @li @c mtx_plain for a simple non-recursive mutex
+ * @li @c mtx_timed for a non-recursive mutex that supports timeout
+ * @li @c mtx_try for a non-recursive mutex that supports test and return
+ * @li @c mtx_plain | @c mtx_recursive (same as @c mtx_plain, but recursive)
+ * @li @c mtx_timed | @c mtx_recursive (same as @c mtx_timed, but recursive)
+ * @li @c mtx_try | @c mtx_recursive (same as @c mtx_try, but recursive)
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int mtx_init(mtx_t *mtx, int type);
/** Release any resources used by the given mutex.
-* @param mtx A mutex object.
-*/
+ * @param mtx A mutex object.
+ */
void mtx_destroy(mtx_t *mtx);
/** Lock the given mutex.
-* Blocks until the given mutex can be locked. If the mutex is non-recursive, and
-* the calling thread already has a lock on the mutex, this call will block
-* forever.
-* @param mtx A mutex object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * Blocks until the given mutex can be locked. If the mutex is non-recursive, and
+ * the calling thread already has a lock on the mutex, this call will block
+ * forever.
+ * @param mtx A mutex object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int mtx_lock(mtx_t *mtx);
/** NOT YET IMPLEMENTED.
-*/
+ */
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
/** Try to lock the given mutex.
-* The specified mutex shall support either test and return or timeout. If the
-* mutex is already locked, the function returns without blocking.
-* @param mtx A mutex object.
-* @return @ref thrd_success on success, or @ref thrd_busy if the resource
-* requested is already in use, or @ref thrd_error if the request could not be
-* honored.
-*/
+ * The specified mutex shall support either test and return or timeout. If the
+ * mutex is already locked, the function returns without blocking.
+ * @param mtx A mutex object.
+ * @return @ref thrd_success on success, or @ref thrd_busy if the resource
+ * requested is already in use, or @ref thrd_error if the request could not be
+ * honored.
+ */
int mtx_trylock(mtx_t *mtx);
/** Unlock the given mutex.
-* @param mtx A mutex object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * @param mtx A mutex object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int mtx_unlock(mtx_t *mtx);
/* Condition variable */
#if defined(_TTHREAD_WIN32_)
typedef struct {
- HANDLE mEvents[2]; /* Signal and broadcast event HANDLEs. */
- unsigned int mWaitersCount; /* Count of the number of waiters. */
- CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */
+ HANDLE mEvents[2]; /* Signal and broadcast event HANDLEs. */
+ unsigned int mWaitersCount; /* Count of the number of waiters. */
+ CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */
} cnd_t;
#else
-typedef pthread_cond_t cnd_t;
+typedef pthread_cond_t cnd_t;
#endif
/** Create a condition variable object.
-* @param cond A condition variable object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * @param cond A condition variable object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int cnd_init(cnd_t *cond);
/** Release any resources used by the given condition variable.
-* @param cond A condition variable object.
-*/
+ * @param cond A condition variable object.
+ */
void cnd_destroy(cnd_t *cond);
/** Signal a condition variable.
-* Unblocks one of the threads that are blocked on the given condition variable
-* at the time of the call. If no threads are blocked on the condition variable
-* at the time of the call, the function does nothing and return success.
-* @param cond A condition variable object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * Unblocks one of the threads that are blocked on the given condition variable
+ * at the time of the call. If no threads are blocked on the condition variable
+ * at the time of the call, the function does nothing and return success.
+ * @param cond A condition variable object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int cnd_signal(cnd_t *cond);
/** Broadcast a condition variable.
-* Unblocks all of the threads that are blocked on the given condition variable
-* at the time of the call. If no threads are blocked on the condition variable
-* at the time of the call, the function does nothing and return success.
-* @param cond A condition variable object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * Unblocks all of the threads that are blocked on the given condition variable
+ * at the time of the call. If no threads are blocked on the condition variable
+ * at the time of the call, the function does nothing and return success.
+ * @param cond A condition variable object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int cnd_broadcast(cnd_t *cond);
/** Wait for a condition variable to become signaled.
-* The function atomically unlocks the given mutex and endeavors to block until
-* the given condition variable is signaled by a call to cnd_signal or to
-* cnd_broadcast. When the calling thread becomes unblocked it locks the mutex
-* before it returns.
-* @param cond A condition variable object.
-* @param mtx A mutex object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * The function atomically unlocks the given mutex and endeavors to block until
+ * the given condition variable is signaled by a call to cnd_signal or to
+ * cnd_broadcast. When the calling thread becomes unblocked it locks the mutex
+ * before it returns.
+ * @param cond A condition variable object.
+ * @param mtx A mutex object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int cnd_wait(cnd_t *cond, mtx_t *mtx);
/** Wait for a condition variable to become signaled.
-* The function atomically unlocks the given mutex and endeavors to block until
-* the given condition variable is signaled by a call to cnd_signal or to
-* cnd_broadcast, or until after the specified time. When the calling thread
-* becomes unblocked it locks the mutex before it returns.
-* @param cond A condition variable object.
-* @param mtx A mutex object.
-* @param xt A point in time at which the request will time out (absolute time).
-* @return @ref thrd_success upon success, or @ref thrd_timeout if the time
-* specified in the call was reached without acquiring the requested resource, or
-* @ref thrd_error if the request could not be honored.
-*/
+ * The function atomically unlocks the given mutex and endeavors to block until
+ * the given condition variable is signaled by a call to cnd_signal or to
+ * cnd_broadcast, or until after the specified time. When the calling thread
+ * becomes unblocked it locks the mutex before it returns.
+ * @param cond A condition variable object.
+ * @param mtx A mutex object.
+ * @param xt A point in time at which the request will time out (absolute time).
+ * @return @ref thrd_success upon success, or @ref thrd_timeout if the time
+ * specified in the call was reached without acquiring the requested resource, or
+ * @ref thrd_error if the request could not be honored.
+ */
int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts);
/* Thread */
#if defined(_TTHREAD_WIN32_)
typedef HANDLE thrd_t;
#else
-typedef pthread_t thrd_t;
+typedef pthread_t thrd_t;
#endif
/** Thread start function.
-* Any thread that is started with the @ref thrd_create() function must be
-* started through a function of this type.
-* @param arg The thread argument (the @c arg argument of the corresponding
-* @ref thrd_create() call).
-* @return The thread return value, which can be obtained by another thread
-* by using the @ref thrd_join() function.
-*/
+ * Any thread that is started with the @ref thrd_create() function must be
+ * started through a function of this type.
+ * @param arg The thread argument (the @c arg argument of the corresponding
+ * @ref thrd_create() call).
+ * @return The thread return value, which can be obtained by another thread
+ * by using the @ref thrd_join() function.
+ */
typedef int (*thrd_start_t)(void *arg);
/** Create a new thread.
-* @param thr Identifier of the newly created thread.
-* @param func A function pointer to the function that will be executed in
-* the new thread.
-* @param arg An argument to the thread function.
-* @return @ref thrd_success on success, or @ref thrd_nomem if no memory could
-* be allocated for the thread requested, or @ref thrd_error if the request
-* could not be honored.
-* @note A thread’s identifier may be reused for a different thread once the
-* original thread has exited and either been detached or joined to another
-* thread.
-*/
+ * @param thr Identifier of the newly created thread.
+ * @param func A function pointer to the function that will be executed in
+ * the new thread.
+ * @param arg An argument to the thread function.
+ * @return @ref thrd_success on success, or @ref thrd_nomem if no memory could
+ * be allocated for the thread requested, or @ref thrd_error if the request
+ * could not be honored.
+ * @note A thread’s identifier may be reused for a different thread once the
+ * original thread has exited and either been detached or joined to another
+ * thread.
+ */
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
/** Identify the calling thread.
-* @return The identifier of the calling thread.
-*/
+ * @return The identifier of the calling thread.
+ */
thrd_t thrd_current(void);
/** NOT YET IMPLEMENTED.
-*/
+ */
int thrd_detach(thrd_t thr);
/** Compare two thread identifiers.
-* The function determines if two thread identifiers refer to the same thread.
-* @return Zero if the two thread identifiers refer to different threads.
-* Otherwise a nonzero value is returned.
-*/
+ * The function determines if two thread identifiers refer to the same thread.
+ * @return Zero if the two thread identifiers refer to different threads.
+ * Otherwise a nonzero value is returned.
+ */
int thrd_equal(thrd_t thr0, thrd_t thr1);
/** Terminate execution of the calling thread.
-* @param res Result code of the calling thread.
-*/
+ * @param res Result code of the calling thread.
+ */
void thrd_exit(int res);
/** Wait for a thread to terminate.
-* The function joins the given thread with the current thread by blocking
-* until the other thread has terminated.
-* @param thr The thread to join with.
-* @param res If this pointer is not NULL, the function will store the result
-* code of the given thread in the integer pointed to by @c res.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * The function joins the given thread with the current thread by blocking
+ * until the other thread has terminated.
+ * @param thr The thread to join with.
+ * @param res If this pointer is not NULL, the function will store the result
+ * code of the given thread in the integer pointed to by @c res.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int thrd_join(thrd_t thr, int *res);
/** Put the calling thread to sleep.
-* Suspend execution of the calling thread.
-* @param time_point A point in time at which the thread will resume (absolute time).
-* @param remaining If non-NULL, this parameter will hold the remaining time until
-* time_point upon return. This will typically be zero, but if
-* the thread was woken up by a signal that is not ignored before
-* time_point was reached @c remaining will hold a positive
-* time.
-* @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
-*/
+ * Suspend execution of the calling thread.
+ * @param time_point A point in time at which the thread will resume (absolute time).
+ * @param remaining If non-NULL, this parameter will hold the remaining time until
+ * time_point upon return. This will typically be zero, but if
+ * the thread was woken up by a signal that is not ignored before
+ * time_point was reached @c remaining will hold a positive
+ * time.
+ * @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
+ */
int thrd_sleep(const struct timespec *time_point, struct timespec *remaining);
/** Yield execution to another thread.
-* Permit other threads to run, even if the current thread would ordinarily
-* continue to run.
-*/
+ * Permit other threads to run, even if the current thread would ordinarily
+ * continue to run.
+ */
void thrd_yield(void);
/* Thread local storage */
#if defined(_TTHREAD_WIN32_)
typedef DWORD tss_t;
#else
-typedef pthread_key_t tss_t;
+typedef pthread_key_t tss_t;
#endif
/** Destructor function for a thread-specific storage.
-* @param val The value of the destructed thread-specific storage.
-*/
+ * @param val The value of the destructed thread-specific storage.
+ */
typedef void (*tss_dtor_t)(void *val);
/** Create a thread-specific storage.
-* @param key The unique key identifier that will be set if the function is
-* successful.
-* @param dtor Destructor function. This can be NULL.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-* @note The destructor function is not supported under Windows. If @c dtor is
-* not NULL when calling this function under Windows, the function will fail
-* and return @ref thrd_error.
-*/
+ * @param key The unique key identifier that will be set if the function is
+ * successful.
+ * @param dtor Destructor function. This can be NULL.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ * @note The destructor function is not supported under Windows. If @c dtor is
+ * not NULL when calling this function under Windows, the function will fail
+ * and return @ref thrd_error.
+ */
int tss_create(tss_t *key, tss_dtor_t dtor);
/** Delete a thread-specific storage.
-* The function releases any resources used by the given thread-specific
-* storage.
-* @param key The key that shall be deleted.
-*/
+ * The function releases any resources used by the given thread-specific
+ * storage.
+ * @param key The key that shall be deleted.
+ */
void tss_delete(tss_t key);
/** Get the value for a thread-specific storage.
-* @param key The thread-specific storage identifier.
-* @return The value for the current thread held in the given thread-specific
-* storage.
-*/
+ * @param key The thread-specific storage identifier.
+ * @return The value for the current thread held in the given thread-specific
+ * storage.
+ */
void *tss_get(tss_t key);
/** Set the value for a thread-specific storage.
-* @param key The thread-specific storage identifier.
-* @param val The value of the thread-specific storage to set for the current
-* thread.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * @param key The thread-specific storage identifier.
+ * @param val The value of the thread-specific storage to set for the current
+ * thread.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int tss_set(tss_t key, void *val);
-
#endif /* _TINYTHREAD_H_ */
-
*
*/
-
#ifndef NANOSVG_H
#define NANOSVG_H
//
// If you don't know or care about the units stuff, "px" and 96 should get you going.
-
/* Example Usage:
- // Load SVG
- NSVGimage* image;
- image = nsvgParseFromFile("test.svg", "px", 96);
- printf("size: %f x %f\n", image->width, image->height);
- // Use...
- for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
- for (NSVGpath *path = shape->paths; path != NULL; path = path->next) {
- for (int i = 0; i < path->npts-1; i += 3) {
- float* p = &path->pts[i*2];
- drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
- }
- }
- }
- // Delete
- nsvgDelete(image);
+ // Load SVG
+ NSVGimage* image;
+ image = nsvgParseFromFile("test.svg", "px", 96);
+ printf("size: %f x %f\n", image->width, image->height);
+ // Use...
+ for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
+ for (NSVGpath *path = shape->paths; path != NULL; path = path->next) {
+ for (int i = 0; i < path->npts-1; i += 3) {
+ float* p = &path->pts[i*2];
+ drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
+ }
+ }
+ }
+ // Delete
+ nsvgDelete(image);
*/
enum NSVGpaintType {
- NSVG_PAINT_NONE = 0,
- NSVG_PAINT_COLOR = 1,
- NSVG_PAINT_LINEAR_GRADIENT = 2,
- NSVG_PAINT_RADIAL_GRADIENT = 3
+ NSVG_PAINT_NONE = 0,
+ NSVG_PAINT_COLOR = 1,
+ NSVG_PAINT_LINEAR_GRADIENT = 2,
+ NSVG_PAINT_RADIAL_GRADIENT = 3
};
-enum NSVGspreadType {
- NSVG_SPREAD_PAD = 0,
- NSVG_SPREAD_REFLECT = 1,
- NSVG_SPREAD_REPEAT = 2
-};
+enum NSVGspreadType { NSVG_SPREAD_PAD = 0, NSVG_SPREAD_REFLECT = 1, NSVG_SPREAD_REPEAT = 2 };
-enum NSVGlineJoin {
- NSVG_JOIN_MITER = 0,
- NSVG_JOIN_ROUND = 1,
- NSVG_JOIN_BEVEL = 2
-};
+enum NSVGlineJoin { NSVG_JOIN_MITER = 0, NSVG_JOIN_ROUND = 1, NSVG_JOIN_BEVEL = 2 };
-enum NSVGlineCap {
- NSVG_CAP_BUTT = 0,
- NSVG_CAP_ROUND = 1,
- NSVG_CAP_SQUARE = 2
-};
+enum NSVGlineCap { NSVG_CAP_BUTT = 0, NSVG_CAP_ROUND = 1, NSVG_CAP_SQUARE = 2 };
-enum NSVGfillRule {
- NSVG_FILLRULE_NONZERO = 0,
- NSVG_FILLRULE_EVENODD = 1
-};
+enum NSVGfillRule { NSVG_FILLRULE_NONZERO = 0, NSVG_FILLRULE_EVENODD = 1 };
-enum NSVGflags {
- NSVG_FLAGS_VISIBLE = 0x01
-};
+enum NSVGflags { NSVG_FLAGS_VISIBLE = 0x01 };
typedef struct NSVGgradientStop {
- unsigned int color;
- float offset;
+ unsigned int color;
+ float offset;
} NSVGgradientStop;
typedef struct NSVGgradient {
- float xform[6];
- char spread;
- float fx, fy;
- int nstops;
- NSVGgradientStop stops[1];
+ float xform[6];
+ char spread;
+ float fx, fy;
+ int nstops;
+ NSVGgradientStop stops[1];
} NSVGgradient;
typedef struct NSVGpaint {
- char type;
- union {
- unsigned int color;
- NSVGgradient* gradient;
- };
+ char type;
+ union {
+ unsigned int color;
+ NSVGgradient *gradient;
+ };
} NSVGpaint;
-typedef struct NSVGpath
-{
- float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
- int npts; // Total number of bezier points.
- char closed; // Flag indicating if shapes should be treated as closed.
- float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
- struct NSVGpath* next; // Pointer to next path, or NULL if last element.
+typedef struct NSVGpath {
+ float *pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
+ int npts; // Total number of bezier points.
+ char closed; // Flag indicating if shapes should be treated as closed.
+ float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
+ struct NSVGpath *next; // Pointer to next path, or NULL if last element.
} NSVGpath;
-typedef struct NSVGshape
-{
- char id[64]; // Optional 'id' attr of the shape or its group
- NSVGpaint fill; // Fill paint
- NSVGpaint stroke; // Stroke paint
- float opacity; // Opacity of the shape.
- float strokeWidth; // Stroke width (scaled).
- float strokeDashOffset; // Stroke dash offset (scaled).
- float strokeDashArray[8]; // Stroke dash array (scaled).
- char strokeDashCount; // Number of dash values in dash array.
- char strokeLineJoin; // Stroke join type.
- char strokeLineCap; // Stroke cap type.
- float miterLimit; // Miter limit
- char fillRule; // Fill rule, see NSVGfillRule.
- unsigned char flags; // Logical or of NSVG_FLAGS_* flags
- float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
- NSVGpath* paths; // Linked list of paths in the image.
- struct NSVGshape* next; // Pointer to next shape, or NULL if last element.
+typedef struct NSVGshape {
+ char id[64]; // Optional 'id' attr of the shape or its group
+ NSVGpaint fill; // Fill paint
+ NSVGpaint stroke; // Stroke paint
+ float opacity; // Opacity of the shape.
+ float strokeWidth; // Stroke width (scaled).
+ float strokeDashOffset; // Stroke dash offset (scaled).
+ float strokeDashArray[8]; // Stroke dash array (scaled).
+ char strokeDashCount; // Number of dash values in dash array.
+ char strokeLineJoin; // Stroke join type.
+ char strokeLineCap; // Stroke cap type.
+ float miterLimit; // Miter limit
+ char fillRule; // Fill rule, see NSVGfillRule.
+ unsigned char flags; // Logical or of NSVG_FLAGS_* flags
+ float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
+ NSVGpath *paths; // Linked list of paths in the image.
+ struct NSVGshape *next; // Pointer to next shape, or NULL if last element.
} NSVGshape;
-typedef struct NSVGimage
-{
- float width; // Width of the image.
- float height; // Height of the image.
- NSVGshape* shapes; // Linked list of shapes in the image.
+typedef struct NSVGimage {
+ float width; // Width of the image.
+ float height; // Height of the image.
+ NSVGshape *shapes; // Linked list of shapes in the image.
} NSVGimage;
// Parses SVG file from a file, returns SVG image as paths.
-NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi);
+NSVGimage *nsvgParseFromFile(const char *filename, const char *units, float dpi);
// Parses SVG file from a null terminated string, returns SVG image as paths.
// Important note: changes the string.
-NSVGimage* nsvgParse(char* input, const char* units, float dpi);
+NSVGimage *nsvgParse(char *input, const char *units, float dpi);
// Duplicates a path.
-NSVGpath* nsvgDuplicatePath(NSVGpath* p);
+NSVGpath *nsvgDuplicatePath(NSVGpath *p);
// Deletes an image.
-void nsvgDelete(NSVGimage* image);
+void nsvgDelete(NSVGimage *image);
#ifndef NANOSVG_CPLUSPLUS
#ifdef __cplusplus
#include <stdlib.h>
#include <math.h>
-#define NSVG_PI (3.14159265358979323846264338327f)
-#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs.
+#define NSVG_PI (3.14159265358979323846264338327f)
+#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs.
-#define NSVG_ALIGN_MIN 0
-#define NSVG_ALIGN_MID 1
-#define NSVG_ALIGN_MAX 2
-#define NSVG_ALIGN_NONE 0
-#define NSVG_ALIGN_MEET 1
+#define NSVG_ALIGN_MIN 0
+#define NSVG_ALIGN_MID 1
+#define NSVG_ALIGN_MAX 2
+#define NSVG_ALIGN_NONE 0
+#define NSVG_ALIGN_MEET 1
#define NSVG_ALIGN_SLICE 2
-#define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0)
+#define NSVG_NOTUSED(v) \
+ do { \
+ (void)(1 ? (void)0 : ((void)(v))); \
+ } while (0)
#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))
#ifdef _MSC_VER
- #pragma warning (disable: 4996) // Switch off security warnings
- #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings
- #ifdef __cplusplus
- #define NSVG_INLINE inline
- #else
- #define NSVG_INLINE
- #endif
+#pragma warning(disable : 4996) // Switch off security warnings
+#pragma warning(disable : 4100) // Switch off unreferenced formal parameter warnings
+#ifdef __cplusplus
+#define NSVG_INLINE inline
+#else
+#define NSVG_INLINE
+#endif
#else
- #define NSVG_INLINE inline
+#define NSVG_INLINE inline
#endif
#ifndef NANOSVG_DEBUG
#define NANOSVG_DEBUG(...)
-//#define NANOSVG_DEBUG printf
+// #define NANOSVG_DEBUG printf
#endif
-static int nsvg__isspace(char c)
-{
- return strchr(" \t\n\v\f\r", c) != 0;
-}
+static int nsvg__isspace(char c) { return strchr(" \t\n\v\f\r", c) != 0; }
-static int nsvg__isdigit(char c)
-{
- return c >= '0' && c <= '9';
-}
+static int nsvg__isdigit(char c) { return c >= '0' && c <= '9'; }
-static int nsvg__isnum(char c)
-{
- return strchr("0123456789+-.eE", c) != 0;
-}
+static int nsvg__isnum(char c) { return strchr("0123456789+-.eE", c) != 0; }
static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; }
static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; }
-
// Simple XML parser
-#define NSVG_XML_TAG 1
-#define NSVG_XML_CONTENT 2
+#define NSVG_XML_TAG 1
+#define NSVG_XML_CONTENT 2
#define NSVG_XML_MAX_ATTRIBS 256
-static void nsvg__parseContent(char* s,
- void (*contentCb)(void* ud, const char* s),
- void* ud)
-{
- // Trim start white spaces
- while (nsvg__isspace(*s)) s++;
- if (!*s) return;
-
- if (contentCb)
- (*contentCb)(ud, s);
-}
-
-static void nsvg__parseElement(char* s,
- void (*startelCb)(void* ud, const char* el, const char** attr),
- void (*endelCb)(void* ud, const char* el),
- void* ud)
-{
- const char* attr[NSVG_XML_MAX_ATTRIBS];
- int nattr = 0;
- char* name;
- int start = 0;
- int end = 0;
- char quote;
-
- // Skip white space after the '<'
- while (nsvg__isspace(*s)) s++;
-
- // Check if the tag is end tag
- if (*s == '/') {
- s++;
- end = 1;
- } else {
- start = 1;
- }
-
- // Skip comments, data and preprocessor stuff.
- if (!*s || *s == '?' || *s == '!')
- return;
-
- // Get tag name
- name = s;
- while (*s && !nsvg__isspace(*s)) s++;
- if (*s) { *s++ = '\0'; }
-
- // Get attribs
- while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) {
- char* name = NULL;
- char* value = NULL;
-
- // Skip white space before the attrib name
- while (nsvg__isspace(*s)) s++;
- if (!*s) break;
- if (*s == '/') {
- end = 1;
- break;
- }
- name = s;
- // Find end of the attrib name.
- while (*s && !nsvg__isspace(*s) && *s != '=') s++;
- if (*s) { *s++ = '\0'; }
- // Skip until the beginning of the value.
- while (*s && *s != '\"' && *s != '\'') s++;
- if (!*s) break;
- quote = *s;
- s++;
- // Store value and find the end of it.
- value = s;
- while (*s && *s != quote) s++;
- if (*s) { *s++ = '\0'; }
-
- // Store only well formed attributes
- if (name && value) {
- attr[nattr++] = name;
- attr[nattr++] = value;
- }
- }
-
- // List terminator
- attr[nattr++] = 0;
- attr[nattr++] = 0;
-
- // Call callbacks.
- if (start && startelCb)
- (*startelCb)(ud, name, attr);
- if (end && endelCb)
- (*endelCb)(ud, name);
-}
-
-int nsvg__parseXML(char* input,
- void (*startelCb)(void* ud, const char* el, const char** attr),
- void (*endelCb)(void* ud, const char* el),
- void (*contentCb)(void* ud, const char* s),
- void* ud)
-{
- char* s = input;
- char* mark = s;
- int state = NSVG_XML_CONTENT;
- while (*s) {
- if (*s == '<' && state == NSVG_XML_CONTENT) {
- // Start of a tag
- *s++ = '\0';
- nsvg__parseContent(mark, contentCb, ud);
- mark = s;
- state = NSVG_XML_TAG;
- } else if (*s == '>' && state == NSVG_XML_TAG) {
- // Start of a content or new tag.
- *s++ = '\0';
- nsvg__parseElement(mark, startelCb, endelCb, ud);
- mark = s;
- state = NSVG_XML_CONTENT;
- } else {
- s++;
- }
- }
-
- return 1;
+static void nsvg__parseContent(char *s, void (*contentCb)(void *ud, const char *s), void *ud) {
+ // Trim start white spaces
+ while (nsvg__isspace(*s))
+ s++;
+ if (!*s)
+ return;
+
+ if (contentCb)
+ (*contentCb)(ud, s);
+}
+
+static void nsvg__parseElement(char *s, void (*startelCb)(void *ud, const char *el, const char **attr),
+ void (*endelCb)(void *ud, const char *el), void *ud) {
+ const char *attr[NSVG_XML_MAX_ATTRIBS];
+ int nattr = 0;
+ char *name;
+ int start = 0;
+ int end = 0;
+ char quote;
+
+ // Skip white space after the '<'
+ while (nsvg__isspace(*s))
+ s++;
+
+ // Check if the tag is end tag
+ if (*s == '/') {
+ s++;
+ end = 1;
+ } else {
+ start = 1;
+ }
+
+ // Skip comments, data and preprocessor stuff.
+ if (!*s || *s == '?' || *s == '!')
+ return;
+
+ // Get tag name
+ name = s;
+ while (*s && !nsvg__isspace(*s))
+ s++;
+ if (*s) {
+ *s++ = '\0';
+ }
+
+ // Get attribs
+ while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS - 3) {
+ char *name = NULL;
+ char *value = NULL;
+
+ // Skip white space before the attrib name
+ while (nsvg__isspace(*s))
+ s++;
+ if (!*s)
+ break;
+ if (*s == '/') {
+ end = 1;
+ break;
+ }
+ name = s;
+ // Find end of the attrib name.
+ while (*s && !nsvg__isspace(*s) && *s != '=')
+ s++;
+ if (*s) {
+ *s++ = '\0';
+ }
+ // Skip until the beginning of the value.
+ while (*s && *s != '\"' && *s != '\'')
+ s++;
+ if (!*s)
+ break;
+ quote = *s;
+ s++;
+ // Store value and find the end of it.
+ value = s;
+ while (*s && *s != quote)
+ s++;
+ if (*s) {
+ *s++ = '\0';
+ }
+
+ // Store only well formed attributes
+ if (name && value) {
+ attr[nattr++] = name;
+ attr[nattr++] = value;
+ }
+ }
+
+ // List terminator
+ attr[nattr++] = 0;
+ attr[nattr++] = 0;
+
+ // Call callbacks.
+ if (start && startelCb)
+ (*startelCb)(ud, name, attr);
+ if (end && endelCb)
+ (*endelCb)(ud, name);
+}
+
+int nsvg__parseXML(char *input, void (*startelCb)(void *ud, const char *el, const char **attr),
+ void (*endelCb)(void *ud, const char *el), void (*contentCb)(void *ud, const char *s), void *ud) {
+ char *s = input;
+ char *mark = s;
+ int state = NSVG_XML_CONTENT;
+ while (*s) {
+ if (*s == '<' && state == NSVG_XML_CONTENT) {
+ // Start of a tag
+ *s++ = '\0';
+ nsvg__parseContent(mark, contentCb, ud);
+ mark = s;
+ state = NSVG_XML_TAG;
+ } else if (*s == '>' && state == NSVG_XML_TAG) {
+ // Start of a content or new tag.
+ *s++ = '\0';
+ nsvg__parseElement(mark, startelCb, endelCb, ud);
+ mark = s;
+ state = NSVG_XML_CONTENT;
+ } else {
+ s++;
+ }
+ }
+
+ return 1;
}
-
/* Simple SVG parser. */
#define NSVG_MAX_ATTR 128
-enum NSVGgradientUnits {
- NSVG_USER_SPACE = 0,
- NSVG_OBJECT_SPACE = 1
-};
+enum NSVGgradientUnits { NSVG_USER_SPACE = 0, NSVG_OBJECT_SPACE = 1 };
#define NSVG_MAX_DASHES 8
enum NSVGunits {
- NSVG_UNITS_USER,
- NSVG_UNITS_PX,
- NSVG_UNITS_PT,
- NSVG_UNITS_PC,
- NSVG_UNITS_MM,
- NSVG_UNITS_CM,
- NSVG_UNITS_IN,
- NSVG_UNITS_PERCENT,
- NSVG_UNITS_EM,
- NSVG_UNITS_EX
+ NSVG_UNITS_USER,
+ NSVG_UNITS_PX,
+ NSVG_UNITS_PT,
+ NSVG_UNITS_PC,
+ NSVG_UNITS_MM,
+ NSVG_UNITS_CM,
+ NSVG_UNITS_IN,
+ NSVG_UNITS_PERCENT,
+ NSVG_UNITS_EM,
+ NSVG_UNITS_EX
};
typedef struct NSVGcoordinate {
- float value;
- int units;
+ float value;
+ int units;
} NSVGcoordinate;
typedef struct NSVGlinearData {
- NSVGcoordinate x1, y1, x2, y2;
+ NSVGcoordinate x1, y1, x2, y2;
} NSVGlinearData;
typedef struct NSVGradialData {
- NSVGcoordinate cx, cy, r, fx, fy;
+ NSVGcoordinate cx, cy, r, fx, fy;
} NSVGradialData;
-typedef struct NSVGgradientData
-{
- char id[64];
- char ref[64];
- char type;
- union {
- NSVGlinearData linear;
- NSVGradialData radial;
- };
- char spread;
- char units;
- float xform[6];
- int nstops;
- NSVGgradientStop* stops;
- struct NSVGgradientData* next;
+typedef struct NSVGgradientData {
+ char id[64];
+ char ref[64];
+ char type;
+ union {
+ NSVGlinearData linear;
+ NSVGradialData radial;
+ };
+ char spread;
+ char units;
+ float xform[6];
+ int nstops;
+ NSVGgradientStop *stops;
+ struct NSVGgradientData *next;
} NSVGgradientData;
-typedef struct NSVGattrib
-{
- char id[64];
- float xform[6];
- unsigned int fillColor;
- unsigned int strokeColor;
- float opacity;
- float fillOpacity;
- float strokeOpacity;
- char fillGradient[64];
- char strokeGradient[64];
- float strokeWidth;
- float strokeDashOffset;
- float strokeDashArray[NSVG_MAX_DASHES];
- int strokeDashCount;
- char strokeLineJoin;
- char strokeLineCap;
- float miterLimit;
- char fillRule;
- float fontSize;
- unsigned int stopColor;
- float stopOpacity;
- float stopOffset;
- char hasFill;
- char hasStroke;
- char visible;
+typedef struct NSVGattrib {
+ char id[64];
+ float xform[6];
+ unsigned int fillColor;
+ unsigned int strokeColor;
+ float opacity;
+ float fillOpacity;
+ float strokeOpacity;
+ char fillGradient[64];
+ char strokeGradient[64];
+ float strokeWidth;
+ float strokeDashOffset;
+ float strokeDashArray[NSVG_MAX_DASHES];
+ int strokeDashCount;
+ char strokeLineJoin;
+ char strokeLineCap;
+ float miterLimit;
+ char fillRule;
+ float fontSize;
+ unsigned int stopColor;
+ float stopOpacity;
+ float stopOffset;
+ char hasFill;
+ char hasStroke;
+ char visible;
} NSVGattrib;
-typedef struct NSVGparser
-{
- NSVGattrib attr[NSVG_MAX_ATTR];
- int attrHead;
- float* pts;
- int npts;
- int cpts;
- NSVGpath* plist;
- NSVGimage* image;
- NSVGgradientData* gradients;
- NSVGshape* shapesTail;
- float viewMinx, viewMiny, viewWidth, viewHeight;
- int alignX, alignY, alignType;
- float dpi;
- char pathFlag;
- char defsFlag;
+typedef struct NSVGparser {
+ NSVGattrib attr[NSVG_MAX_ATTR];
+ int attrHead;
+ float *pts;
+ int npts;
+ int cpts;
+ NSVGpath *plist;
+ NSVGimage *image;
+ NSVGgradientData *gradients;
+ NSVGshape *shapesTail;
+ float viewMinx, viewMiny, viewWidth, viewHeight;
+ int alignX, alignY, alignType;
+ float dpi;
+ char pathFlag;
+ char defsFlag;
} NSVGparser;
-static void nsvg__xformIdentity(float* t)
-{
- t[0] = 1.0f; t[1] = 0.0f;
- t[2] = 0.0f; t[3] = 1.0f;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetTranslation(float* t, float tx, float ty)
-{
- t[0] = 1.0f; t[1] = 0.0f;
- t[2] = 0.0f; t[3] = 1.0f;
- t[4] = tx; t[5] = ty;
-}
-
-static void nsvg__xformSetScale(float* t, float sx, float sy)
-{
- t[0] = sx; t[1] = 0.0f;
- t[2] = 0.0f; t[3] = sy;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetSkewX(float* t, float a)
-{
- t[0] = 1.0f; t[1] = 0.0f;
- t[2] = tanf(a); t[3] = 1.0f;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetSkewY(float* t, float a)
-{
- t[0] = 1.0f; t[1] = tanf(a);
- t[2] = 0.0f; t[3] = 1.0f;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetRotation(float* t, float a)
-{
- float cs = cosf(a), sn = sinf(a);
- t[0] = cs; t[1] = sn;
- t[2] = -sn; t[3] = cs;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformMultiply(float* t, float* s)
-{
- float t0 = t[0] * s[0] + t[1] * s[2];
- float t2 = t[2] * s[0] + t[3] * s[2];
- float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
- t[1] = t[0] * s[1] + t[1] * s[3];
- t[3] = t[2] * s[1] + t[3] * s[3];
- t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
- t[0] = t0;
- t[2] = t2;
- t[4] = t4;
-}
-
-static void nsvg__xformInverse(float* inv, float* t)
-{
- double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
- if (det > -1e-6 && det < 1e-6) {
- nsvg__xformIdentity(t);
- return;
- }
- invdet = 1.0 / det;
- inv[0] = (float)(t[3] * invdet);
- inv[2] = (float)(-t[2] * invdet);
- inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
- inv[1] = (float)(-t[1] * invdet);
- inv[3] = (float)(t[0] * invdet);
- inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
-}
-
-static void nsvg__xformPremultiply(float* t, float* s)
-{
- float s2[6];
- memcpy(s2, s, sizeof(float)*6);
- nsvg__xformMultiply(s2, t);
- memcpy(t, s2, sizeof(float)*6);
-}
-
-static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t)
-{
- *dx = x*t[0] + y*t[2] + t[4];
- *dy = x*t[1] + y*t[3] + t[5];
-}
-
-static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t)
-{
- *dx = x*t[0] + y*t[2];
- *dy = x*t[1] + y*t[3];
+static void nsvg__xformIdentity(float *t) {
+ t[0] = 1.0f;
+ t[1] = 0.0f;
+ t[2] = 0.0f;
+ t[3] = 1.0f;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetTranslation(float *t, float tx, float ty) {
+ t[0] = 1.0f;
+ t[1] = 0.0f;
+ t[2] = 0.0f;
+ t[3] = 1.0f;
+ t[4] = tx;
+ t[5] = ty;
+}
+
+static void nsvg__xformSetScale(float *t, float sx, float sy) {
+ t[0] = sx;
+ t[1] = 0.0f;
+ t[2] = 0.0f;
+ t[3] = sy;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetSkewX(float *t, float a) {
+ t[0] = 1.0f;
+ t[1] = 0.0f;
+ t[2] = tanf(a);
+ t[3] = 1.0f;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetSkewY(float *t, float a) {
+ t[0] = 1.0f;
+ t[1] = tanf(a);
+ t[2] = 0.0f;
+ t[3] = 1.0f;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetRotation(float *t, float a) {
+ float cs = cosf(a), sn = sinf(a);
+ t[0] = cs;
+ t[1] = sn;
+ t[2] = -sn;
+ t[3] = cs;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformMultiply(float *t, float *s) {
+ float t0 = t[0] * s[0] + t[1] * s[2];
+ float t2 = t[2] * s[0] + t[3] * s[2];
+ float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
+ t[1] = t[0] * s[1] + t[1] * s[3];
+ t[3] = t[2] * s[1] + t[3] * s[3];
+ t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
+ t[0] = t0;
+ t[2] = t2;
+ t[4] = t4;
+}
+
+static void nsvg__xformInverse(float *inv, float *t) {
+ double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
+ if (det > -1e-6 && det < 1e-6) {
+ nsvg__xformIdentity(t);
+ return;
+ }
+ invdet = 1.0 / det;
+ inv[0] = (float)(t[3] * invdet);
+ inv[2] = (float)(-t[2] * invdet);
+ inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
+ inv[1] = (float)(-t[1] * invdet);
+ inv[3] = (float)(t[0] * invdet);
+ inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
+}
+
+static void nsvg__xformPremultiply(float *t, float *s) {
+ float s2[6];
+ memcpy(s2, s, sizeof(float) * 6);
+ nsvg__xformMultiply(s2, t);
+ memcpy(t, s2, sizeof(float) * 6);
+}
+
+static void nsvg__xformPoint(float *dx, float *dy, float x, float y, float *t) {
+ *dx = x * t[0] + y * t[2] + t[4];
+ *dy = x * t[1] + y * t[3] + t[5];
+}
+
+static void nsvg__xformVec(float *dx, float *dy, float x, float y, float *t) {
+ *dx = x * t[0] + y * t[2];
+ *dy = x * t[1] + y * t[3];
}
#define NSVG_EPSILON (1e-12)
-static int nsvg__ptInBounds(float* pt, float* bounds)
-{
- return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];
-}
-
-
-static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3)
-{
- double it = 1.0-t;
- return it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3;
-}
-
-static void nsvg__curveBounds(float* bounds, float* curve)
-{
- int i, j, count;
- double roots[2], a, b, c, b2ac, t, v;
- float* v0 = &curve[0];
- float* v1 = &curve[2];
- float* v2 = &curve[4];
- float* v3 = &curve[6];
-
- // Start the bounding box by end points
- bounds[0] = nsvg__minf(v0[0], v3[0]);
- bounds[1] = nsvg__minf(v0[1], v3[1]);
- bounds[2] = nsvg__maxf(v0[0], v3[0]);
- bounds[3] = nsvg__maxf(v0[1], v3[1]);
-
- // Bezier curve fits inside the convex hull of it's control points.
- // If control points are inside the bounds, we're done.
- if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))
- return;
-
- // Add bezier curve inflection points in X and Y.
- for (i = 0; i < 2; i++) {
- a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i];
- b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i];
- c = 3.0 * v1[i] - 3.0 * v0[i];
- count = 0;
- if (fabs(a) < NSVG_EPSILON) {
- if (fabs(b) > NSVG_EPSILON) {
- t = -c / b;
- if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
- roots[count++] = t;
- }
- } else {
- b2ac = b*b - 4.0*c*a;
- if (b2ac > NSVG_EPSILON) {
- t = (-b + sqrt(b2ac)) / (2.0 * a);
- if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
- roots[count++] = t;
- t = (-b - sqrt(b2ac)) / (2.0 * a);
- if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
- roots[count++] = t;
- }
- }
- for (j = 0; j < count; j++) {
- v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);
- bounds[0+i] = nsvg__minf(bounds[0+i], (float)v);
- bounds[2+i] = nsvg__maxf(bounds[2+i], (float)v);
- }
- }
-}
-
-static NSVGparser* nsvg__createParser()
-{
- NSVGparser* p;
- p = (NSVGparser*)malloc(sizeof(NSVGparser));
- if (p == NULL) goto error;
- memset(p, 0, sizeof(NSVGparser));
-
- p->image = (NSVGimage*)malloc(sizeof(NSVGimage));
- if (p->image == NULL) goto error;
- memset(p->image, 0, sizeof(NSVGimage));
-
- // Init style
- nsvg__xformIdentity(p->attr[0].xform);
- memset(p->attr[0].id, 0, sizeof p->attr[0].id);
- p->attr[0].fillColor = NSVG_RGB(0,0,0);
- p->attr[0].strokeColor = NSVG_RGB(0,0,0);
- p->attr[0].opacity = 1;
- p->attr[0].fillOpacity = 1;
- p->attr[0].strokeOpacity = 1;
- p->attr[0].stopOpacity = 1;
- p->attr[0].strokeWidth = 1;
- p->attr[0].strokeLineJoin = NSVG_JOIN_MITER;
- p->attr[0].strokeLineCap = NSVG_CAP_BUTT;
- p->attr[0].miterLimit = 4;
- p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
- p->attr[0].hasFill = 1;
- p->attr[0].visible = 1;
-
- return p;
+static int nsvg__ptInBounds(float *pt, float *bounds) {
+ return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];
+}
+
+static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3) {
+ double it = 1.0 - t;
+ return it * it * it * p0 + 3.0 * it * it * t * p1 + 3.0 * it * t * t * p2 + t * t * t * p3;
+}
+
+static void nsvg__curveBounds(float *bounds, float *curve) {
+ int i, j, count;
+ double roots[2], a, b, c, b2ac, t, v;
+ float *v0 = &curve[0];
+ float *v1 = &curve[2];
+ float *v2 = &curve[4];
+ float *v3 = &curve[6];
+
+ // Start the bounding box by end points
+ bounds[0] = nsvg__minf(v0[0], v3[0]);
+ bounds[1] = nsvg__minf(v0[1], v3[1]);
+ bounds[2] = nsvg__maxf(v0[0], v3[0]);
+ bounds[3] = nsvg__maxf(v0[1], v3[1]);
+
+ // Bezier curve fits inside the convex hull of it's control points.
+ // If control points are inside the bounds, we're done.
+ if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))
+ return;
+
+ // Add bezier curve inflection points in X and Y.
+ for (i = 0; i < 2; i++) {
+ a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i];
+ b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i];
+ c = 3.0 * v1[i] - 3.0 * v0[i];
+ count = 0;
+ if (fabs(a) < NSVG_EPSILON) {
+ if (fabs(b) > NSVG_EPSILON) {
+ t = -c / b;
+ if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON)
+ roots[count++] = t;
+ }
+ } else {
+ b2ac = b * b - 4.0 * c * a;
+ if (b2ac > NSVG_EPSILON) {
+ t = (-b + sqrt(b2ac)) / (2.0 * a);
+ if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON)
+ roots[count++] = t;
+ t = (-b - sqrt(b2ac)) / (2.0 * a);
+ if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON)
+ roots[count++] = t;
+ }
+ }
+ for (j = 0; j < count; j++) {
+ v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);
+ bounds[0 + i] = nsvg__minf(bounds[0 + i], (float)v);
+ bounds[2 + i] = nsvg__maxf(bounds[2 + i], (float)v);
+ }
+ }
+}
+
+static NSVGparser *nsvg__createParser() {
+ NSVGparser *p;
+ p = (NSVGparser *)malloc(sizeof(NSVGparser));
+ if (p == NULL)
+ goto error;
+ memset(p, 0, sizeof(NSVGparser));
+
+ p->image = (NSVGimage *)malloc(sizeof(NSVGimage));
+ if (p->image == NULL)
+ goto error;
+ memset(p->image, 0, sizeof(NSVGimage));
+
+ // Init style
+ nsvg__xformIdentity(p->attr[0].xform);
+ memset(p->attr[0].id, 0, sizeof p->attr[0].id);
+ p->attr[0].fillColor = NSVG_RGB(0, 0, 0);
+ p->attr[0].strokeColor = NSVG_RGB(0, 0, 0);
+ p->attr[0].opacity = 1;
+ p->attr[0].fillOpacity = 1;
+ p->attr[0].strokeOpacity = 1;
+ p->attr[0].stopOpacity = 1;
+ p->attr[0].strokeWidth = 1;
+ p->attr[0].strokeLineJoin = NSVG_JOIN_MITER;
+ p->attr[0].strokeLineCap = NSVG_CAP_BUTT;
+ p->attr[0].miterLimit = 4;
+ p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
+ p->attr[0].hasFill = 1;
+ p->attr[0].visible = 1;
+
+ return p;
error:
- if (p) {
- if (p->image) free(p->image);
- free(p);
- }
- return NULL;
-}
-
-static void nsvg__deletePaths(NSVGpath* path)
-{
- while (path) {
- NSVGpath *next = path->next;
- if (path->pts != NULL)
- free(path->pts);
- free(path);
- path = next;
- }
-}
-
-static void nsvg__deletePaint(NSVGpaint* paint)
-{
- if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT)
- free(paint->gradient);
+ if (p) {
+ if (p->image)
+ free(p->image);
+ free(p);
+ }
+ return NULL;
}
-
-static void nsvg__deleteGradientData(NSVGgradientData* grad)
-{
- NSVGgradientData* next;
- while (grad != NULL) {
- next = grad->next;
- free(grad->stops);
- free(grad);
- grad = next;
- }
+
+static void nsvg__deletePaths(NSVGpath *path) {
+ while (path) {
+ NSVGpath *next = path->next;
+ if (path->pts != NULL)
+ free(path->pts);
+ free(path);
+ path = next;
+ }
}
-static void nsvg__deleteParser(NSVGparser* p)
-{
- if (p != NULL) {
- nsvg__deletePaths(p->plist);
- nsvg__deleteGradientData(p->gradients);
- nsvgDelete(p->image);
- free(p->pts);
- free(p);
- }
+static void nsvg__deletePaint(NSVGpaint *paint) {
+ if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT)
+ free(paint->gradient);
}
-static void nsvg__resetPath(NSVGparser* p)
-{
- p->npts = 0;
-}
-
-static void nsvg__addPoint(NSVGparser* p, float x, float y)
-{
- if (p->npts+1 > p->cpts) {
- p->cpts = p->cpts ? p->cpts*2 : 8;
- p->pts = (float*)realloc(p->pts, p->cpts*2*sizeof(float));
- if (!p->pts) return;
- }
- p->pts[p->npts*2+0] = x;
- p->pts[p->npts*2+1] = y;
- p->npts++;
-}
-
-static void nsvg__moveTo(NSVGparser* p, float x, float y)
-{
- if (p->npts > 0) {
- p->pts[(p->npts-1)*2+0] = x;
- p->pts[(p->npts-1)*2+1] = y;
- } else {
- nsvg__addPoint(p, x, y);
- }
-}
-
-static void nsvg__lineTo(NSVGparser* p, float x, float y)
-{
- float px,py, dx,dy;
- if (p->npts > 0) {
- px = p->pts[(p->npts-1)*2+0];
- py = p->pts[(p->npts-1)*2+1];
- dx = x - px;
- dy = y - py;
- nsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f);
- nsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f);
- nsvg__addPoint(p, x, y);
- }
-}
-
-static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)
-{
- nsvg__addPoint(p, cpx1, cpy1);
- nsvg__addPoint(p, cpx2, cpy2);
- nsvg__addPoint(p, x, y);
-}
-
-static NSVGattrib* nsvg__getAttr(NSVGparser* p)
-{
- return &p->attr[p->attrHead];
-}
-
-static void nsvg__pushAttr(NSVGparser* p)
-{
- if (p->attrHead < NSVG_MAX_ATTR-1) {
- p->attrHead++;
- memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead-1], sizeof(NSVGattrib));
- }
-}
-
-static void nsvg__popAttr(NSVGparser* p)
-{
- if (p->attrHead > 0)
- p->attrHead--;
-}
-
-static float nsvg__actualOrigX(NSVGparser* p)
-{
- return p->viewMinx;
-}
-
-static float nsvg__actualOrigY(NSVGparser* p)
-{
- return p->viewMiny;
-}
-
-static float nsvg__actualWidth(NSVGparser* p)
-{
- return p->viewWidth;
-}
-
-static float nsvg__actualHeight(NSVGparser* p)
-{
- return p->viewHeight;
-}
-
-static float nsvg__actualLength(NSVGparser* p)
-{
- float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p);
- return sqrtf(w*w + h*h) / sqrtf(2.0f);
-}
-
-static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- switch (c.units) {
- case NSVG_UNITS_USER: return c.value;
- case NSVG_UNITS_PX: return c.value;
- case NSVG_UNITS_PT: return c.value / 72.0f * p->dpi;
- case NSVG_UNITS_PC: return c.value / 6.0f * p->dpi;
- case NSVG_UNITS_MM: return c.value / 25.4f * p->dpi;
- case NSVG_UNITS_CM: return c.value / 2.54f * p->dpi;
- case NSVG_UNITS_IN: return c.value * p->dpi;
- case NSVG_UNITS_EM: return c.value * attr->fontSize;
- case NSVG_UNITS_EX: return c.value * attr->fontSize * 0.52f; // x-height of Helvetica.
- case NSVG_UNITS_PERCENT: return orig + c.value / 100.0f * length;
- default: return c.value;
- }
- return c.value;
-}
-
-static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id)
-{
- NSVGgradientData* grad = p->gradients;
- while (grad) {
- if (strcmp(grad->id, id) == 0)
- return grad;
- grad = grad->next;
- }
- return NULL;
-}
-
-static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, char* paintType)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- NSVGgradientData* data = NULL;
- NSVGgradientData* ref = NULL;
- NSVGgradientStop* stops = NULL;
- NSVGgradient* grad;
- float ox, oy, sw, sh, sl;
- int nstops = 0;
-
- data = nsvg__findGradientData(p, id);
- if (data == NULL) return NULL;
-
- // TODO: use ref to fill in all unset values too.
- ref = data;
- while (ref != NULL) {
- if (stops == NULL && ref->stops != NULL) {
- stops = ref->stops;
- nstops = ref->nstops;
- break;
- }
- ref = nsvg__findGradientData(p, ref->ref);
- }
- if (stops == NULL) return NULL;
-
- grad = (NSVGgradient*)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop)*(nstops-1));
- if (grad == NULL) return NULL;
-
- // The shape width and height.
- if (data->units == NSVG_OBJECT_SPACE) {
- ox = localBounds[0];
- oy = localBounds[1];
- sw = localBounds[2] - localBounds[0];
- sh = localBounds[3] - localBounds[1];
- } else {
- ox = nsvg__actualOrigX(p);
- oy = nsvg__actualOrigY(p);
- sw = nsvg__actualWidth(p);
- sh = nsvg__actualHeight(p);
- }
- sl = sqrtf(sw*sw + sh*sh) / sqrtf(2.0f);
-
- if (data->type == NSVG_PAINT_LINEAR_GRADIENT) {
- float x1, y1, x2, y2, dx, dy;
- x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw);
- y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh);
- x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw);
- y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh);
- // Calculate transform aligned to the line
- dx = x2 - x1;
- dy = y2 - y1;
- grad->xform[0] = dy; grad->xform[1] = -dx;
- grad->xform[2] = dx; grad->xform[3] = dy;
- grad->xform[4] = x1; grad->xform[5] = y1;
- } else {
- float cx, cy, fx, fy, r;
- cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw);
- cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh);
- fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw);
- fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh);
- r = nsvg__convertToPixels(p, data->radial.r, 0, sl);
- // Calculate transform aligned to the circle
- grad->xform[0] = r; grad->xform[1] = 0;
- grad->xform[2] = 0; grad->xform[3] = r;
- grad->xform[4] = cx; grad->xform[5] = cy;
- grad->fx = fx / r;
- grad->fy = fy / r;
- }
-
- nsvg__xformMultiply(grad->xform, data->xform);
- nsvg__xformMultiply(grad->xform, attr->xform);
-
- grad->spread = data->spread;
- memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));
- grad->nstops = nstops;
-
- *paintType = data->type;
-
- return grad;
-}
-
-static float nsvg__getAverageScale(float* t)
-{
- float sx = sqrtf(t[0]*t[0] + t[2]*t[2]);
- float sy = sqrtf(t[1]*t[1] + t[3]*t[3]);
- return (sx + sy) * 0.5f;
-}
-
-static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform)
-{
- NSVGpath* path;
- float curve[4*2], curveBounds[4];
- int i, first = 1;
- for (path = shape->paths; path != NULL; path = path->next) {
- nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform);
- for (i = 0; i < path->npts-1; i += 3) {
- nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i+1)*2], path->pts[(i+1)*2+1], xform);
- nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i+2)*2], path->pts[(i+2)*2+1], xform);
- nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i+3)*2], path->pts[(i+3)*2+1], xform);
- nsvg__curveBounds(curveBounds, curve);
- if (first) {
- bounds[0] = curveBounds[0];
- bounds[1] = curveBounds[1];
- bounds[2] = curveBounds[2];
- bounds[3] = curveBounds[3];
- first = 0;
- } else {
- bounds[0] = nsvg__minf(bounds[0], curveBounds[0]);
- bounds[1] = nsvg__minf(bounds[1], curveBounds[1]);
- bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);
- bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);
- }
- curve[0] = curve[6];
- curve[1] = curve[7];
- }
- }
-}
-
-static void nsvg__addShape(NSVGparser* p)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- float scale = 1.0f;
- NSVGshape* shape;
- NSVGpath* path;
- int i;
-
- if (p->plist == NULL)
- return;
-
- shape = (NSVGshape*)malloc(sizeof(NSVGshape));
- if (shape == NULL) goto error;
- memset(shape, 0, sizeof(NSVGshape));
-
- memcpy(shape->id, attr->id, sizeof shape->id);
- scale = nsvg__getAverageScale(attr->xform);
- shape->strokeWidth = attr->strokeWidth * scale;
- shape->strokeDashOffset = attr->strokeDashOffset * scale;
- shape->strokeDashCount = (char)attr->strokeDashCount;
- for (i = 0; i < attr->strokeDashCount; i++)
- shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
- shape->strokeLineJoin = attr->strokeLineJoin;
- shape->strokeLineCap = attr->strokeLineCap;
- shape->miterLimit = attr->miterLimit;
- shape->fillRule = attr->fillRule;
- shape->opacity = attr->opacity;
-
- shape->paths = p->plist;
- p->plist = NULL;
-
- // Calculate shape bounds
- shape->bounds[0] = shape->paths->bounds[0];
- shape->bounds[1] = shape->paths->bounds[1];
- shape->bounds[2] = shape->paths->bounds[2];
- shape->bounds[3] = shape->paths->bounds[3];
- for (path = shape->paths->next; path != NULL; path = path->next) {
- shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
- shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);
- shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);
- shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);
- }
-
- // Set fill
- if (attr->hasFill == 0) {
- shape->fill.type = NSVG_PAINT_NONE;
- } else if (attr->hasFill == 1) {
- shape->fill.type = NSVG_PAINT_COLOR;
- shape->fill.color = attr->fillColor;
- shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24;
- } else if (attr->hasFill == 2) {
- float inv[6], localBounds[4];
- nsvg__xformInverse(inv, attr->xform);
- nsvg__getLocalBounds(localBounds, shape, inv);
- shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type);
- if (shape->fill.gradient == NULL) {
- shape->fill.type = NSVG_PAINT_NONE;
- }
- }
-
- // Set stroke
- if (attr->hasStroke == 0) {
- shape->stroke.type = NSVG_PAINT_NONE;
- } else if (attr->hasStroke == 1) {
- shape->stroke.type = NSVG_PAINT_COLOR;
- shape->stroke.color = attr->strokeColor;
- shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24;
- } else if (attr->hasStroke == 2) {
- float inv[6], localBounds[4];
- nsvg__xformInverse(inv, attr->xform);
- nsvg__getLocalBounds(localBounds, shape, inv);
- shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type);
- if (shape->stroke.gradient == NULL)
- shape->stroke.type = NSVG_PAINT_NONE;
- }
-
- // Set flags
- shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00);
-
- // Add to tail
- if (p->image->shapes == NULL)
- p->image->shapes = shape;
- else
- p->shapesTail->next = shape;
- p->shapesTail = shape;
-
- return;
+static void nsvg__deleteGradientData(NSVGgradientData *grad) {
+ NSVGgradientData *next;
+ while (grad != NULL) {
+ next = grad->next;
+ free(grad->stops);
+ free(grad);
+ grad = next;
+ }
+}
+
+static void nsvg__deleteParser(NSVGparser *p) {
+ if (p != NULL) {
+ nsvg__deletePaths(p->plist);
+ nsvg__deleteGradientData(p->gradients);
+ nsvgDelete(p->image);
+ free(p->pts);
+ free(p);
+ }
+}
+
+static void nsvg__resetPath(NSVGparser *p) { p->npts = 0; }
+
+static void nsvg__addPoint(NSVGparser *p, float x, float y) {
+ if (p->npts + 1 > p->cpts) {
+ p->cpts = p->cpts ? p->cpts * 2 : 8;
+ p->pts = (float *)realloc(p->pts, p->cpts * 2 * sizeof(float));
+ if (!p->pts)
+ return;
+ }
+ p->pts[p->npts * 2 + 0] = x;
+ p->pts[p->npts * 2 + 1] = y;
+ p->npts++;
+}
+
+static void nsvg__moveTo(NSVGparser *p, float x, float y) {
+ if (p->npts > 0) {
+ p->pts[(p->npts - 1) * 2 + 0] = x;
+ p->pts[(p->npts - 1) * 2 + 1] = y;
+ } else {
+ nsvg__addPoint(p, x, y);
+ }
+}
+
+static void nsvg__lineTo(NSVGparser *p, float x, float y) {
+ float px, py, dx, dy;
+ if (p->npts > 0) {
+ px = p->pts[(p->npts - 1) * 2 + 0];
+ py = p->pts[(p->npts - 1) * 2 + 1];
+ dx = x - px;
+ dy = y - py;
+ nsvg__addPoint(p, px + dx / 3.0f, py + dy / 3.0f);
+ nsvg__addPoint(p, x - dx / 3.0f, y - dy / 3.0f);
+ nsvg__addPoint(p, x, y);
+ }
+}
+
+static void nsvg__cubicBezTo(NSVGparser *p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y) {
+ nsvg__addPoint(p, cpx1, cpy1);
+ nsvg__addPoint(p, cpx2, cpy2);
+ nsvg__addPoint(p, x, y);
+}
+
+static NSVGattrib *nsvg__getAttr(NSVGparser *p) { return &p->attr[p->attrHead]; }
+
+static void nsvg__pushAttr(NSVGparser *p) {
+ if (p->attrHead < NSVG_MAX_ATTR - 1) {
+ p->attrHead++;
+ memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead - 1], sizeof(NSVGattrib));
+ }
+}
+
+static void nsvg__popAttr(NSVGparser *p) {
+ if (p->attrHead > 0)
+ p->attrHead--;
+}
+
+static float nsvg__actualOrigX(NSVGparser *p) { return p->viewMinx; }
+
+static float nsvg__actualOrigY(NSVGparser *p) { return p->viewMiny; }
+
+static float nsvg__actualWidth(NSVGparser *p) { return p->viewWidth; }
+
+static float nsvg__actualHeight(NSVGparser *p) { return p->viewHeight; }
+
+static float nsvg__actualLength(NSVGparser *p) {
+ float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p);
+ return sqrtf(w * w + h * h) / sqrtf(2.0f);
+}
+
+static float nsvg__convertToPixels(NSVGparser *p, NSVGcoordinate c, float orig, float length) {
+ NSVGattrib *attr = nsvg__getAttr(p);
+ switch (c.units) {
+ case NSVG_UNITS_USER:
+ return c.value;
+ case NSVG_UNITS_PX:
+ return c.value;
+ case NSVG_UNITS_PT:
+ return c.value / 72.0f * p->dpi;
+ case NSVG_UNITS_PC:
+ return c.value / 6.0f * p->dpi;
+ case NSVG_UNITS_MM:
+ return c.value / 25.4f * p->dpi;
+ case NSVG_UNITS_CM:
+ return c.value / 2.54f * p->dpi;
+ case NSVG_UNITS_IN:
+ return c.value * p->dpi;
+ case NSVG_UNITS_EM:
+ return c.value * attr->fontSize;
+ case NSVG_UNITS_EX:
+ return c.value * attr->fontSize * 0.52f; // x-height of Helvetica.
+ case NSVG_UNITS_PERCENT:
+ return orig + c.value / 100.0f * length;
+ default:
+ return c.value;
+ }
+ return c.value;
+}
+
+static NSVGgradientData *nsvg__findGradientData(NSVGparser *p, const char *id) {
+ NSVGgradientData *grad = p->gradients;
+ while (grad) {
+ if (strcmp(grad->id, id) == 0)
+ return grad;
+ grad = grad->next;
+ }
+ return NULL;
+}
+
+static NSVGgradient *nsvg__createGradient(NSVGparser *p, const char *id, const float *localBounds, char *paintType) {
+ NSVGattrib *attr = nsvg__getAttr(p);
+ NSVGgradientData *data = NULL;
+ NSVGgradientData *ref = NULL;
+ NSVGgradientStop *stops = NULL;
+ NSVGgradient *grad;
+ float ox, oy, sw, sh, sl;
+ int nstops = 0;
+
+ data = nsvg__findGradientData(p, id);
+ if (data == NULL)
+ return NULL;
+
+ // TODO: use ref to fill in all unset values too.
+ ref = data;
+ while (ref != NULL) {
+ if (stops == NULL && ref->stops != NULL) {
+ stops = ref->stops;
+ nstops = ref->nstops;
+ break;
+ }
+ ref = nsvg__findGradientData(p, ref->ref);
+ }
+ if (stops == NULL)
+ return NULL;
+
+ grad = (NSVGgradient *)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop) * (nstops - 1));
+ if (grad == NULL)
+ return NULL;
+
+ // The shape width and height.
+ if (data->units == NSVG_OBJECT_SPACE) {
+ ox = localBounds[0];
+ oy = localBounds[1];
+ sw = localBounds[2] - localBounds[0];
+ sh = localBounds[3] - localBounds[1];
+ } else {
+ ox = nsvg__actualOrigX(p);
+ oy = nsvg__actualOrigY(p);
+ sw = nsvg__actualWidth(p);
+ sh = nsvg__actualHeight(p);
+ }
+ sl = sqrtf(sw * sw + sh * sh) / sqrtf(2.0f);
+
+ if (data->type == NSVG_PAINT_LINEAR_GRADIENT) {
+ float x1, y1, x2, y2, dx, dy;
+ x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw);
+ y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh);
+ x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw);
+ y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh);
+ // Calculate transform aligned to the line
+ dx = x2 - x1;
+ dy = y2 - y1;
+ grad->xform[0] = dy;
+ grad->xform[1] = -dx;
+ grad->xform[2] = dx;
+ grad->xform[3] = dy;
+ grad->xform[4] = x1;
+ grad->xform[5] = y1;
+ } else {
+ float cx, cy, fx, fy, r;
+ cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw);
+ cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh);
+ fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw);
+ fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh);
+ r = nsvg__convertToPixels(p, data->radial.r, 0, sl);
+ // Calculate transform aligned to the circle
+ grad->xform[0] = r;
+ grad->xform[1] = 0;
+ grad->xform[2] = 0;
+ grad->xform[3] = r;
+ grad->xform[4] = cx;
+ grad->xform[5] = cy;
+ grad->fx = fx / r;
+ grad->fy = fy / r;
+ }
+
+ nsvg__xformMultiply(grad->xform, data->xform);
+ nsvg__xformMultiply(grad->xform, attr->xform);
+
+ grad->spread = data->spread;
+ memcpy(grad->stops, stops, nstops * sizeof(NSVGgradientStop));
+ grad->nstops = nstops;
+
+ *paintType = data->type;
+
+ return grad;
+}
+
+static float nsvg__getAverageScale(float *t) {
+ float sx = sqrtf(t[0] * t[0] + t[2] * t[2]);
+ float sy = sqrtf(t[1] * t[1] + t[3] * t[3]);
+ return (sx + sy) * 0.5f;
+}
+
+static void nsvg__getLocalBounds(float *bounds, NSVGshape *shape, float *xform) {
+ NSVGpath *path;
+ float curve[4 * 2], curveBounds[4];
+ int i, first = 1;
+ for (path = shape->paths; path != NULL; path = path->next) {
+ nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform);
+ for (i = 0; i < path->npts - 1; i += 3) {
+ nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i + 1) * 2], path->pts[(i + 1) * 2 + 1], xform);
+ nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i + 2) * 2], path->pts[(i + 2) * 2 + 1], xform);
+ nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i + 3) * 2], path->pts[(i + 3) * 2 + 1], xform);
+ nsvg__curveBounds(curveBounds, curve);
+ if (first) {
+ bounds[0] = curveBounds[0];
+ bounds[1] = curveBounds[1];
+ bounds[2] = curveBounds[2];
+ bounds[3] = curveBounds[3];
+ first = 0;
+ } else {
+ bounds[0] = nsvg__minf(bounds[0], curveBounds[0]);
+ bounds[1] = nsvg__minf(bounds[1], curveBounds[1]);
+ bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);
+ bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);
+ }
+ curve[0] = curve[6];
+ curve[1] = curve[7];
+ }
+ }
+}
+
+static void nsvg__addShape(NSVGparser *p) {
+ NSVGattrib *attr = nsvg__getAttr(p);
+ float scale = 1.0f;
+ NSVGshape *shape;
+ NSVGpath *path;
+ int i;
+
+ if (p->plist == NULL)
+ return;
+
+ shape = (NSVGshape *)malloc(sizeof(NSVGshape));
+ if (shape == NULL)
+ goto error;
+ memset(shape, 0, sizeof(NSVGshape));
+
+ memcpy(shape->id, attr->id, sizeof shape->id);
+ scale = nsvg__getAverageScale(attr->xform);
+ shape->strokeWidth = attr->strokeWidth * scale;
+ shape->strokeDashOffset = attr->strokeDashOffset * scale;
+ shape->strokeDashCount = (char)attr->strokeDashCount;
+ for (i = 0; i < attr->strokeDashCount; i++)
+ shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
+ shape->strokeLineJoin = attr->strokeLineJoin;
+ shape->strokeLineCap = attr->strokeLineCap;
+ shape->miterLimit = attr->miterLimit;
+ shape->fillRule = attr->fillRule;
+ shape->opacity = attr->opacity;
+
+ shape->paths = p->plist;
+ p->plist = NULL;
+
+ // Calculate shape bounds
+ shape->bounds[0] = shape->paths->bounds[0];
+ shape->bounds[1] = shape->paths->bounds[1];
+ shape->bounds[2] = shape->paths->bounds[2];
+ shape->bounds[3] = shape->paths->bounds[3];
+ for (path = shape->paths->next; path != NULL; path = path->next) {
+ shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
+ shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);
+ shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);
+ shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);
+ }
+
+ // Set fill
+ if (attr->hasFill == 0) {
+ shape->fill.type = NSVG_PAINT_NONE;
+ } else if (attr->hasFill == 1) {
+ shape->fill.type = NSVG_PAINT_COLOR;
+ shape->fill.color = attr->fillColor;
+ shape->fill.color |= (unsigned int)(attr->fillOpacity * 255) << 24;
+ } else if (attr->hasFill == 2) {
+ float inv[6], localBounds[4];
+ nsvg__xformInverse(inv, attr->xform);
+ nsvg__getLocalBounds(localBounds, shape, inv);
+ shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type);
+ if (shape->fill.gradient == NULL) {
+ shape->fill.type = NSVG_PAINT_NONE;
+ }
+ }
+
+ // Set stroke
+ if (attr->hasStroke == 0) {
+ shape->stroke.type = NSVG_PAINT_NONE;
+ } else if (attr->hasStroke == 1) {
+ shape->stroke.type = NSVG_PAINT_COLOR;
+ shape->stroke.color = attr->strokeColor;
+ shape->stroke.color |= (unsigned int)(attr->strokeOpacity * 255) << 24;
+ } else if (attr->hasStroke == 2) {
+ float inv[6], localBounds[4];
+ nsvg__xformInverse(inv, attr->xform);
+ nsvg__getLocalBounds(localBounds, shape, inv);
+ shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type);
+ if (shape->stroke.gradient == NULL)
+ shape->stroke.type = NSVG_PAINT_NONE;
+ }
+
+ // Set flags
+ shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00);
+
+ // Add to tail
+ if (p->image->shapes == NULL)
+ p->image->shapes = shape;
+ else
+ p->shapesTail->next = shape;
+ p->shapesTail = shape;
+
+ return;
error:
- if (shape) free(shape);
-}
-
-static void nsvg__addPath(NSVGparser* p, char closed)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- NSVGpath* path = NULL;
- float bounds[4];
- float* curve;
- int i;
-
- if (p->npts < 4)
- return;
-
- if (closed)
- nsvg__lineTo(p, p->pts[0], p->pts[1]);
-
- path = (NSVGpath*)malloc(sizeof(NSVGpath));
- if (path == NULL) goto error;
- memset(path, 0, sizeof(NSVGpath));
-
- path->pts = (float*)malloc(p->npts*2*sizeof(float));
- if (path->pts == NULL) goto error;
- path->closed = closed;
- path->npts = p->npts;
-
- // Transform path.
- for (i = 0; i < p->npts; ++i)
- nsvg__xformPoint(&path->pts[i*2], &path->pts[i*2+1], p->pts[i*2], p->pts[i*2+1], attr->xform);
-
- // Find bounds
- for (i = 0; i < path->npts-1; i += 3) {
- curve = &path->pts[i*2];
- nsvg__curveBounds(bounds, curve);
- if (i == 0) {
- path->bounds[0] = bounds[0];
- path->bounds[1] = bounds[1];
- path->bounds[2] = bounds[2];
- path->bounds[3] = bounds[3];
- } else {
- path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]);
- path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]);
- path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]);
- path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]);
- }
- }
-
- path->next = p->plist;
- p->plist = path;
-
- return;
+ if (shape)
+ free(shape);
+}
+
+static void nsvg__addPath(NSVGparser *p, char closed) {
+ NSVGattrib *attr = nsvg__getAttr(p);
+ NSVGpath *path = NULL;
+ float bounds[4];
+ float *curve;
+ int i;
+
+ if (p->npts < 4)
+ return;
+
+ if (closed)
+ nsvg__lineTo(p, p->pts[0], p->pts[1]);
+
+ path = (NSVGpath *)malloc(sizeof(NSVGpath));
+ if (path == NULL)
+ goto error;
+ memset(path, 0, sizeof(NSVGpath));
+
+ path->pts = (float *)malloc(p->npts * 2 * sizeof(float));
+ if (path->pts == NULL)
+ goto error;
+ path->closed = closed;
+ path->npts = p->npts;
+
+ // Transform path.
+ for (i = 0; i < p->npts; ++i)
+ nsvg__xformPoint(&path->pts[i * 2], &path->pts[i * 2 + 1], p->pts[i * 2], p->pts[i * 2 + 1], attr->xform);
+
+ // Find bounds
+ for (i = 0; i < path->npts - 1; i += 3) {
+ curve = &path->pts[i * 2];
+ nsvg__curveBounds(bounds, curve);
+ if (i == 0) {
+ path->bounds[0] = bounds[0];
+ path->bounds[1] = bounds[1];
+ path->bounds[2] = bounds[2];
+ path->bounds[3] = bounds[3];
+ } else {
+ path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]);
+ path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]);
+ path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]);
+ path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]);
+ }
+ }
+
+ path->next = p->plist;
+ p->plist = path;
+
+ return;
error:
- if (path != NULL) {
- if (path->pts != NULL) free(path->pts);
- free(path);
- }
+ if (path != NULL) {
+ if (path->pts != NULL)
+ free(path->pts);
+ free(path);
+ }
}
// We roll our own string to float because the std library one uses locale and messes things up.
-static double nsvg__atof(const char* s)
-{
- char* cur = (char*)s;
- char* end = NULL;
- double res = 0.0, sign = 1.0;
- long long intPart = 0, fracPart = 0;
- char hasIntPart = 0, hasFracPart = 0;
-
- // Parse optional sign
- if (*cur == '+') {
- cur++;
- } else if (*cur == '-') {
- sign = -1;
- cur++;
- }
-
- // Parse integer part
- if (nsvg__isdigit(*cur)) {
- // Parse digit sequence
- intPart = (double)strtoll(cur, &end, 10);
- if (cur != end) {
- res = (double)intPart;
- hasIntPart = 1;
- cur = end;
- }
- }
-
- // Parse fractional part.
- if (*cur == '.') {
- cur++; // Skip '.'
- if (nsvg__isdigit(*cur)) {
- // Parse digit sequence
- fracPart = strtoll(cur, &end, 10);
- if (cur != end) {
- res += (double)fracPart / pow(10.0, (double)(end - cur));
- hasFracPart = 1;
- cur = end;
- }
- }
- }
-
- // A valid number should have integer or fractional part.
- if (!hasIntPart && !hasFracPart)
- return 0.0;
-
- // Parse optional exponent
- if (*cur == 'e' || *cur == 'E') {
- long expPart = 0;
- cur++; // skip 'E'
- expPart = strtol(cur, &end, 10); // Parse digit sequence with sign
- if (cur != end) {
- res *= pow(10.0, (double)expPart);
- }
- }
-
- return res * sign;
-}
-
-
-static const char* nsvg__parseNumber(const char* s, char* it, const int size)
-{
- const int last = size-1;
- int i = 0;
-
- // sign
- if (*s == '-' || *s == '+') {
- if (i < last) it[i++] = *s;
- s++;
- }
- // integer part
- // leading zero
- if (*s == '0') {
- if (i < last) it[i++] = *s;
- s++;
- }
- else
- while (nsvg__isdigit(*s)) {
- if (i < last) it[i++] = *s;
- s++;
- }
- if (*s == '.') {
- // decimal point
- if (i < last) it[i++] = *s;
- s++;
- // fraction part
- while (nsvg__isdigit(*s)) {
- if (i < last) it[i++] = *s;
- s++;
- }
- }
- // exponent
- if ((*s == 'e' || *s == 'E') && (s[1] != 'm' && s[1] != 'x')) {
- if (i < last) it[i++] = *s;
- s++;
- if (*s == '-' || *s == '+') {
- if (i < last) it[i++] = *s;
- s++;
- }
- while (nsvg__isdigit(*s)) {
- if (i < last) it[i++] = *s;
- s++;
- }
- }
- it[i] = '\0';
-
- return s;
-}
-
-static const char* nsvg__getNextPathItemWhenArcFlag(const char* s, char* it)
-{
- it[0] = '\0';
- while (nsvg__isspace(*s) || *s == ',') s++;
- if (*s == '0' || *s == '1') {
- it[0] = *s++;
- it[1] = '\0';
- return s;
- }
- return s;
-}
-
-static const char* nsvg__getNextPathItem(const char* s, char* it)
-{
- it[0] = '\0';
- // Skip white spaces and commas
- while (nsvg__isspace(*s) || *s == ',') s++;
- if (!*s) return s;
- if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) {
- s = nsvg__parseNumber(s, it, 64);
- } else {
- // Parse command
- it[0] = *s++;
- it[1] = '\0';
- return s;
- }
-
- return s;
-}
-
-static unsigned int nsvg__parseColorHex(const char* str)
-{
- unsigned int c = 0, r = 0, g = 0, b = 0;
- int n = 0;
- str++; // skip #
- // Calculate number of characters.
- while(str[n] && !nsvg__isspace(str[n]))
- n++;
- if (n == 6) {
- sscanf(str, "%x", &c);
- } else if (n == 3) {
- sscanf(str, "%x", &c);
- c = (c&0xf) | ((c&0xf0) << 4) | ((c&0xf00) << 8);
- c |= c<<4;
- }
- r = (c >> 16) & 0xff;
- g = (c >> 8) & 0xff;
- b = c & 0xff;
- return NSVG_RGB(r,g,b);
-}
-
-static unsigned int nsvg__parseColorRGB(const char* str)
-{
- int r = -1, g = -1, b = -1;
- char s1[32]="", s2[32]="";
- sscanf(str + 4, "%d%[%%, \t]%d%[%%, \t]%d", &r, s1, &g, s2, &b);
- if (strchr(s1, '%')) {
- return NSVG_RGB((r*255)/100,(g*255)/100,(b*255)/100);
- } else {
- return NSVG_RGB(r,g,b);
- }
+static double nsvg__atof(const char *s) {
+ char *cur = (char *)s;
+ char *end = NULL;
+ double res = 0.0, sign = 1.0;
+ long long intPart = 0, fracPart = 0;
+ char hasIntPart = 0, hasFracPart = 0;
+
+ // Parse optional sign
+ if (*cur == '+') {
+ cur++;
+ } else if (*cur == '-') {
+ sign = -1;
+ cur++;
+ }
+
+ // Parse integer part
+ if (nsvg__isdigit(*cur)) {
+ // Parse digit sequence
+ intPart = (double)strtoll(cur, &end, 10);
+ if (cur != end) {
+ res = (double)intPart;
+ hasIntPart = 1;
+ cur = end;
+ }
+ }
+
+ // Parse fractional part.
+ if (*cur == '.') {
+ cur++; // Skip '.'
+ if (nsvg__isdigit(*cur)) {
+ // Parse digit sequence
+ fracPart = strtoll(cur, &end, 10);
+ if (cur != end) {
+ res += (double)fracPart / pow(10.0, (double)(end - cur));
+ hasFracPart = 1;
+ cur = end;
+ }
+ }
+ }
+
+ // A valid number should have integer or fractional part.
+ if (!hasIntPart && !hasFracPart)
+ return 0.0;
+
+ // Parse optional exponent
+ if (*cur == 'e' || *cur == 'E') {
+ long expPart = 0;
+ cur++; // skip 'E'
+ expPart = strtol(cur, &end, 10); // Parse digit sequence with sign
+ if (cur != end) {
+ res *= pow(10.0, (double)expPart);
+ }
+ }
+
+ return res * sign;
+}
+
+static const char *nsvg__parseNumber(const char *s, char *it, const int size) {
+ const int last = size - 1;
+ int i = 0;
+
+ // sign
+ if (*s == '-' || *s == '+') {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ // integer part
+ // leading zero
+ if (*s == '0') {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ } else
+ while (nsvg__isdigit(*s)) {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ if (*s == '.') {
+ // decimal point
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ // fraction part
+ while (nsvg__isdigit(*s)) {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ }
+ // exponent
+ if ((*s == 'e' || *s == 'E') && (s[1] != 'm' && s[1] != 'x')) {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ if (*s == '-' || *s == '+') {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ while (nsvg__isdigit(*s)) {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ }
+ it[i] = '\0';
+
+ return s;
+}
+
+static const char *nsvg__getNextPathItemWhenArcFlag(const char *s, char *it) {
+ it[0] = '\0';
+ while (nsvg__isspace(*s) || *s == ',')
+ s++;
+ if (*s == '0' || *s == '1') {
+ it[0] = *s++;
+ it[1] = '\0';
+ return s;
+ }
+ return s;
+}
+
+static const char *nsvg__getNextPathItem(const char *s, char *it) {
+ it[0] = '\0';
+ // Skip white spaces and commas
+ while (nsvg__isspace(*s) || *s == ',')
+ s++;
+ if (!*s)
+ return s;
+ if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) {
+ s = nsvg__parseNumber(s, it, 64);
+ } else {
+ // Parse command
+ it[0] = *s++;
+ it[1] = '\0';
+ return s;
+ }
+
+ return s;
+}
+
+static unsigned int nsvg__parseColorHex(const char *str) {
+ unsigned int c = 0, r = 0, g = 0, b = 0;
+ int n = 0;
+ str++; // skip #
+ // Calculate number of characters.
+ while (str[n] && !nsvg__isspace(str[n]))
+ n++;
+ if (n == 6) {
+ sscanf(str, "%x", &c);
+ } else if (n == 3) {
+ sscanf(str, "%x", &c);
+ c = (c & 0xf) | ((c & 0xf0) << 4) | ((c & 0xf00) << 8);
+ c |= c << 4;
+ }
+ r = (c >> 16) & 0xff;
+ g = (c >> 8) & 0xff;
+ b = c & 0xff;
+ return NSVG_RGB(r, g, b);
+}
+
+static unsigned int nsvg__parseColorRGB(const char *str) {
+ int r = -1, g = -1, b = -1;
+ char s1[32] = "", s2[32] = "";
+ sscanf(str + 4, "%d%[%%, \t]%d%[%%, \t]%d", &r, s1, &g, s2, &b);
+ if (strchr(s1, '%')) {
+ return NSVG_RGB((r * 255) / 100, (g * 255) / 100, (b * 255) / 100);
+ } else {
+ return NSVG_RGB(r, g, b);
+ }
}
typedef struct NSVGNamedColor {
- const char* name;
- unsigned int color;
+ const char *name;
+ unsigned int color;
} NSVGNamedColor;
NSVGNamedColor nsvg__colors[] = {
- { "red", NSVG_RGB(255, 0, 0) },
- { "green", NSVG_RGB( 0, 128, 0) },
- { "blue", NSVG_RGB( 0, 0, 255) },
- { "yellow", NSVG_RGB(255, 255, 0) },
- { "cyan", NSVG_RGB( 0, 255, 255) },
- { "magenta", NSVG_RGB(255, 0, 255) },
- { "black", NSVG_RGB( 0, 0, 0) },
- { "grey", NSVG_RGB(128, 128, 128) },
- { "gray", NSVG_RGB(128, 128, 128) },
- { "white", NSVG_RGB(255, 255, 255) },
+ {"red", NSVG_RGB(255, 0, 0)},
+ {"green", NSVG_RGB(0, 128, 0)},
+ {"blue", NSVG_RGB(0, 0, 255)},
+ {"yellow", NSVG_RGB(255, 255, 0)},
+ {"cyan", NSVG_RGB(0, 255, 255)},
+ {"magenta", NSVG_RGB(255, 0, 255)},
+ {"black", NSVG_RGB(0, 0, 0)},
+ {"grey", NSVG_RGB(128, 128, 128)},
+ {"gray", NSVG_RGB(128, 128, 128)},
+ {"white", NSVG_RGB(255, 255, 255)},
#ifdef NANOSVG_ALL_COLOR_KEYWORDS
- { "aliceblue", NSVG_RGB(240, 248, 255) },
- { "antiquewhite", NSVG_RGB(250, 235, 215) },
- { "aqua", NSVG_RGB( 0, 255, 255) },
- { "aquamarine", NSVG_RGB(127, 255, 212) },
- { "azure", NSVG_RGB(240, 255, 255) },
- { "beige", NSVG_RGB(245, 245, 220) },
- { "bisque", NSVG_RGB(255, 228, 196) },
- { "blanchedalmond", NSVG_RGB(255, 235, 205) },
- { "blueviolet", NSVG_RGB(138, 43, 226) },
- { "brown", NSVG_RGB(165, 42, 42) },
- { "burlywood", NSVG_RGB(222, 184, 135) },
- { "cadetblue", NSVG_RGB( 95, 158, 160) },
- { "chartreuse", NSVG_RGB(127, 255, 0) },
- { "chocolate", NSVG_RGB(210, 105, 30) },
- { "coral", NSVG_RGB(255, 127, 80) },
- { "cornflowerblue", NSVG_RGB(100, 149, 237) },
- { "cornsilk", NSVG_RGB(255, 248, 220) },
- { "crimson", NSVG_RGB(220, 20, 60) },
- { "darkblue", NSVG_RGB( 0, 0, 139) },
- { "darkcyan", NSVG_RGB( 0, 139, 139) },
- { "darkgoldenrod", NSVG_RGB(184, 134, 11) },
- { "darkgray", NSVG_RGB(169, 169, 169) },
- { "darkgreen", NSVG_RGB( 0, 100, 0) },
- { "darkgrey", NSVG_RGB(169, 169, 169) },
- { "darkkhaki", NSVG_RGB(189, 183, 107) },
- { "darkmagenta", NSVG_RGB(139, 0, 139) },
- { "darkolivegreen", NSVG_RGB( 85, 107, 47) },
- { "darkorange", NSVG_RGB(255, 140, 0) },
- { "darkorchid", NSVG_RGB(153, 50, 204) },
- { "darkred", NSVG_RGB(139, 0, 0) },
- { "darksalmon", NSVG_RGB(233, 150, 122) },
- { "darkseagreen", NSVG_RGB(143, 188, 143) },
- { "darkslateblue", NSVG_RGB( 72, 61, 139) },
- { "darkslategray", NSVG_RGB( 47, 79, 79) },
- { "darkslategrey", NSVG_RGB( 47, 79, 79) },
- { "darkturquoise", NSVG_RGB( 0, 206, 209) },
- { "darkviolet", NSVG_RGB(148, 0, 211) },
- { "deeppink", NSVG_RGB(255, 20, 147) },
- { "deepskyblue", NSVG_RGB( 0, 191, 255) },
- { "dimgray", NSVG_RGB(105, 105, 105) },
- { "dimgrey", NSVG_RGB(105, 105, 105) },
- { "dodgerblue", NSVG_RGB( 30, 144, 255) },
- { "firebrick", NSVG_RGB(178, 34, 34) },
- { "floralwhite", NSVG_RGB(255, 250, 240) },
- { "forestgreen", NSVG_RGB( 34, 139, 34) },
- { "fuchsia", NSVG_RGB(255, 0, 255) },
- { "gainsboro", NSVG_RGB(220, 220, 220) },
- { "ghostwhite", NSVG_RGB(248, 248, 255) },
- { "gold", NSVG_RGB(255, 215, 0) },
- { "goldenrod", NSVG_RGB(218, 165, 32) },
- { "greenyellow", NSVG_RGB(173, 255, 47) },
- { "honeydew", NSVG_RGB(240, 255, 240) },
- { "hotpink", NSVG_RGB(255, 105, 180) },
- { "indianred", NSVG_RGB(205, 92, 92) },
- { "indigo", NSVG_RGB( 75, 0, 130) },
- { "ivory", NSVG_RGB(255, 255, 240) },
- { "khaki", NSVG_RGB(240, 230, 140) },
- { "lavender", NSVG_RGB(230, 230, 250) },
- { "lavenderblush", NSVG_RGB(255, 240, 245) },
- { "lawngreen", NSVG_RGB(124, 252, 0) },
- { "lemonchiffon", NSVG_RGB(255, 250, 205) },
- { "lightblue", NSVG_RGB(173, 216, 230) },
- { "lightcoral", NSVG_RGB(240, 128, 128) },
- { "lightcyan", NSVG_RGB(224, 255, 255) },
- { "lightgoldenrodyellow", NSVG_RGB(250, 250, 210) },
- { "lightgray", NSVG_RGB(211, 211, 211) },
- { "lightgreen", NSVG_RGB(144, 238, 144) },
- { "lightgrey", NSVG_RGB(211, 211, 211) },
- { "lightpink", NSVG_RGB(255, 182, 193) },
- { "lightsalmon", NSVG_RGB(255, 160, 122) },
- { "lightseagreen", NSVG_RGB( 32, 178, 170) },
- { "lightskyblue", NSVG_RGB(135, 206, 250) },
- { "lightslategray", NSVG_RGB(119, 136, 153) },
- { "lightslategrey", NSVG_RGB(119, 136, 153) },
- { "lightsteelblue", NSVG_RGB(176, 196, 222) },
- { "lightyellow", NSVG_RGB(255, 255, 224) },
- { "lime", NSVG_RGB( 0, 255, 0) },
- { "limegreen", NSVG_RGB( 50, 205, 50) },
- { "linen", NSVG_RGB(250, 240, 230) },
- { "maroon", NSVG_RGB(128, 0, 0) },
- { "mediumaquamarine", NSVG_RGB(102, 205, 170) },
- { "mediumblue", NSVG_RGB( 0, 0, 205) },
- { "mediumorchid", NSVG_RGB(186, 85, 211) },
- { "mediumpurple", NSVG_RGB(147, 112, 219) },
- { "mediumseagreen", NSVG_RGB( 60, 179, 113) },
- { "mediumslateblue", NSVG_RGB(123, 104, 238) },
- { "mediumspringgreen", NSVG_RGB( 0, 250, 154) },
- { "mediumturquoise", NSVG_RGB( 72, 209, 204) },
- { "mediumvioletred", NSVG_RGB(199, 21, 133) },
- { "midnightblue", NSVG_RGB( 25, 25, 112) },
- { "mintcream", NSVG_RGB(245, 255, 250) },
- { "mistyrose", NSVG_RGB(255, 228, 225) },
- { "moccasin", NSVG_RGB(255, 228, 181) },
- { "navajowhite", NSVG_RGB(255, 222, 173) },
- { "navy", NSVG_RGB( 0, 0, 128) },
- { "oldlace", NSVG_RGB(253, 245, 230) },
- { "olive", NSVG_RGB(128, 128, 0) },
- { "olivedrab", NSVG_RGB(107, 142, 35) },
- { "orange", NSVG_RGB(255, 165, 0) },
- { "orangered", NSVG_RGB(255, 69, 0) },
- { "orchid", NSVG_RGB(218, 112, 214) },
- { "palegoldenrod", NSVG_RGB(238, 232, 170) },
- { "palegreen", NSVG_RGB(152, 251, 152) },
- { "paleturquoise", NSVG_RGB(175, 238, 238) },
- { "palevioletred", NSVG_RGB(219, 112, 147) },
- { "papayawhip", NSVG_RGB(255, 239, 213) },
- { "peachpuff", NSVG_RGB(255, 218, 185) },
- { "peru", NSVG_RGB(205, 133, 63) },
- { "pink", NSVG_RGB(255, 192, 203) },
- { "plum", NSVG_RGB(221, 160, 221) },
- { "powderblue", NSVG_RGB(176, 224, 230) },
- { "purple", NSVG_RGB(128, 0, 128) },
- { "rosybrown", NSVG_RGB(188, 143, 143) },
- { "royalblue", NSVG_RGB( 65, 105, 225) },
- { "saddlebrown", NSVG_RGB(139, 69, 19) },
- { "salmon", NSVG_RGB(250, 128, 114) },
- { "sandybrown", NSVG_RGB(244, 164, 96) },
- { "seagreen", NSVG_RGB( 46, 139, 87) },
- { "seashell", NSVG_RGB(255, 245, 238) },
- { "sienna", NSVG_RGB(160, 82, 45) },
- { "silver", NSVG_RGB(192, 192, 192) },
- { "skyblue", NSVG_RGB(135, 206, 235) },
- { "slateblue", NSVG_RGB(106, 90, 205) },
- { "slategray", NSVG_RGB(112, 128, 144) },
- { "slategrey", NSVG_RGB(112, 128, 144) },
- { "snow", NSVG_RGB(255, 250, 250) },
- { "springgreen", NSVG_RGB( 0, 255, 127) },
- { "steelblue", NSVG_RGB( 70, 130, 180) },
- { "tan", NSVG_RGB(210, 180, 140) },
- { "teal", NSVG_RGB( 0, 128, 128) },
- { "thistle", NSVG_RGB(216, 191, 216) },
- { "tomato", NSVG_RGB(255, 99, 71) },
- { "turquoise", NSVG_RGB( 64, 224, 208) },
- { "violet", NSVG_RGB(238, 130, 238) },
- { "wheat", NSVG_RGB(245, 222, 179) },
- { "whitesmoke", NSVG_RGB(245, 245, 245) },
- { "yellowgreen", NSVG_RGB(154, 205, 50) },
+ {"aliceblue", NSVG_RGB(240, 248, 255)},
+ {"antiquewhite", NSVG_RGB(250, 235, 215)},
+ {"aqua", NSVG_RGB(0, 255, 255)},
+ {"aquamarine", NSVG_RGB(127, 255, 212)},
+ {"azure", NSVG_RGB(240, 255, 255)},
+ {"beige", NSVG_RGB(245, 245, 220)},
+ {"bisque", NSVG_RGB(255, 228, 196)},
+ {"blanchedalmond", NSVG_RGB(255, 235, 205)},
+ {"blueviolet", NSVG_RGB(138, 43, 226)},
+ {"brown", NSVG_RGB(165, 42, 42)},
+ {"burlywood", NSVG_RGB(222, 184, 135)},
+ {"cadetblue", NSVG_RGB(95, 158, 160)},
+ {"chartreuse", NSVG_RGB(127, 255, 0)},
+ {"chocolate", NSVG_RGB(210, 105, 30)},
+ {"coral", NSVG_RGB(255, 127, 80)},
+ {"cornflowerblue", NSVG_RGB(100, 149, 237)},
+ {"cornsilk", NSVG_RGB(255, 248, 220)},
+ {"crimson", NSVG_RGB(220, 20, 60)},
+ {"darkblue", NSVG_RGB(0, 0, 139)},
+ {"darkcyan", NSVG_RGB(0, 139, 139)},
+ {"darkgoldenrod", NSVG_RGB(184, 134, 11)},
+ {"darkgray", NSVG_RGB(169, 169, 169)},
+ {"darkgreen", NSVG_RGB(0, 100, 0)},
+ {"darkgrey", NSVG_RGB(169, 169, 169)},
+ {"darkkhaki", NSVG_RGB(189, 183, 107)},
+ {"darkmagenta", NSVG_RGB(139, 0, 139)},
+ {"darkolivegreen", NSVG_RGB(85, 107, 47)},
+ {"darkorange", NSVG_RGB(255, 140, 0)},
+ {"darkorchid", NSVG_RGB(153, 50, 204)},
+ {"darkred", NSVG_RGB(139, 0, 0)},
+ {"darksalmon", NSVG_RGB(233, 150, 122)},
+ {"darkseagreen", NSVG_RGB(143, 188, 143)},
+ {"darkslateblue", NSVG_RGB(72, 61, 139)},
+ {"darkslategray", NSVG_RGB(47, 79, 79)},
+ {"darkslategrey", NSVG_RGB(47, 79, 79)},
+ {"darkturquoise", NSVG_RGB(0, 206, 209)},
+ {"darkviolet", NSVG_RGB(148, 0, 211)},
+ {"deeppink", NSVG_RGB(255, 20, 147)},
+ {"deepskyblue", NSVG_RGB(0, 191, 255)},
+ {"dimgray", NSVG_RGB(105, 105, 105)},
+ {"dimgrey", NSVG_RGB(105, 105, 105)},
+ {"dodgerblue", NSVG_RGB(30, 144, 255)},
+ {"firebrick", NSVG_RGB(178, 34, 34)},
+ {"floralwhite", NSVG_RGB(255, 250, 240)},
+ {"forestgreen", NSVG_RGB(34, 139, 34)},
+ {"fuchsia", NSVG_RGB(255, 0, 255)},
+ {"gainsboro", NSVG_RGB(220, 220, 220)},
+ {"ghostwhite", NSVG_RGB(248, 248, 255)},
+ {"gold", NSVG_RGB(255, 215, 0)},
+ {"goldenrod", NSVG_RGB(218, 165, 32)},
+ {"greenyellow", NSVG_RGB(173, 255, 47)},
+ {"honeydew", NSVG_RGB(240, 255, 240)},
+ {"hotpink", NSVG_RGB(255, 105, 180)},
+ {"indianred", NSVG_RGB(205, 92, 92)},
+ {"indigo", NSVG_RGB(75, 0, 130)},
+ {"ivory", NSVG_RGB(255, 255, 240)},
+ {"khaki", NSVG_RGB(240, 230, 140)},
+ {"lavender", NSVG_RGB(230, 230, 250)},
+ {"lavenderblush", NSVG_RGB(255, 240, 245)},
+ {"lawngreen", NSVG_RGB(124, 252, 0)},
+ {"lemonchiffon", NSVG_RGB(255, 250, 205)},
+ {"lightblue", NSVG_RGB(173, 216, 230)},
+ {"lightcoral", NSVG_RGB(240, 128, 128)},
+ {"lightcyan", NSVG_RGB(224, 255, 255)},
+ {"lightgoldenrodyellow", NSVG_RGB(250, 250, 210)},
+ {"lightgray", NSVG_RGB(211, 211, 211)},
+ {"lightgreen", NSVG_RGB(144, 238, 144)},
+ {"lightgrey", NSVG_RGB(211, 211, 211)},
+ {"lightpink", NSVG_RGB(255, 182, 193)},
+ {"lightsalmon", NSVG_RGB(255, 160, 122)},
+ {"lightseagreen", NSVG_RGB(32, 178, 170)},
+ {"lightskyblue", NSVG_RGB(135, 206, 250)},
+ {"lightslategray", NSVG_RGB(119, 136, 153)},
+ {"lightslategrey", NSVG_RGB(119, 136, 153)},
+ {"lightsteelblue", NSVG_RGB(176, 196, 222)},
+ {"lightyellow", NSVG_RGB(255, 255, 224)},
+ {"lime", NSVG_RGB(0, 255, 0)},
+ {"limegreen", NSVG_RGB(50, 205, 50)},
+ {"linen", NSVG_RGB(250, 240, 230)},
+ {"maroon", NSVG_RGB(128, 0, 0)},
+ {"mediumaquamarine", NSVG_RGB(102, 205, 170)},
+ {"mediumblue", NSVG_RGB(0, 0, 205)},
+ {"mediumorchid", NSVG_RGB(186, 85, 211)},
+ {"mediumpurple", NSVG_RGB(147, 112, 219)},
+ {"mediumseagreen", NSVG_RGB(60, 179, 113)},
+ {"mediumslateblue", NSVG_RGB(123, 104, 238)},
+ {"mediumspringgreen", NSVG_RGB(0, 250, 154)},
+ {"mediumturquoise", NSVG_RGB(72, 209, 204)},
+ {"mediumvioletred", NSVG_RGB(199, 21, 133)},
+ {"midnightblue", NSVG_RGB(25, 25, 112)},
+ {"mintcream", NSVG_RGB(245, 255, 250)},
+ {"mistyrose", NSVG_RGB(255, 228, 225)},
+ {"moccasin", NSVG_RGB(255, 228, 181)},
+ {"navajowhite", NSVG_RGB(255, 222, 173)},
+ {"navy", NSVG_RGB(0, 0, 128)},
+ {"oldlace", NSVG_RGB(253, 245, 230)},
+ {"olive", NSVG_RGB(128, 128, 0)},
+ {"olivedrab", NSVG_RGB(107, 142, 35)},
+ {"orange", NSVG_RGB(255, 165, 0)},
+ {"orangered", NSVG_RGB(255, 69, 0)},
+ {"orchid", NSVG_RGB(218, 112, 214)},
+ {"palegoldenrod", NSVG_RGB(238, 232, 170)},
+ {"palegreen", NSVG_RGB(152, 251, 152)},
+ {"paleturquoise", NSVG_RGB(175, 238, 238)},
+ {"palevioletred", NSVG_RGB(219, 112, 147)},
+ {"papayawhip", NSVG_RGB(255, 239, 213)},
+ {"peachpuff", NSVG_RGB(255, 218, 185)},
+ {"peru", NSVG_RGB(205, 133, 63)},
+ {"pink", NSVG_RGB(255, 192, 203)},
+ {"plum", NSVG_RGB(221, 160, 221)},
+ {"powderblue", NSVG_RGB(176, 224, 230)},
+ {"purple", NSVG_RGB(128, 0, 128)},
+ {"rosybrown", NSVG_RGB(188, 143, 143)},
+ {"royalblue", NSVG_RGB(65, 105, 225)},
+ {"saddlebrown", NSVG_RGB(139, 69, 19)},
+ {"salmon", NSVG_RGB(250, 128, 114)},
+ {"sandybrown", NSVG_RGB(244, 164, 96)},
+ {"seagreen", NSVG_RGB(46, 139, 87)},
+ {"seashell", NSVG_RGB(255, 245, 238)},
+ {"sienna", NSVG_RGB(160, 82, 45)},
+ {"silver", NSVG_RGB(192, 192, 192)},
+ {"skyblue", NSVG_RGB(135, 206, 235)},
+ {"slateblue", NSVG_RGB(106, 90, 205)},
+ {"slategray", NSVG_RGB(112, 128, 144)},
+ {"slategrey", NSVG_RGB(112, 128, 144)},
+ {"snow", NSVG_RGB(255, 250, 250)},
+ {"springgreen", NSVG_RGB(0, 255, 127)},
+ {"steelblue", NSVG_RGB(70, 130, 180)},
+ {"tan", NSVG_RGB(210, 180, 140)},
+ {"teal", NSVG_RGB(0, 128, 128)},
+ {"thistle", NSVG_RGB(216, 191, 216)},
+ {"tomato", NSVG_RGB(255, 99, 71)},
+ {"turquoise", NSVG_RGB(64, 224, 208)},
+ {"violet", NSVG_RGB(238, 130, 238)},
+ {"wheat", NSVG_RGB(245, 222, 179)},
+ {"whitesmoke", NSVG_RGB(245, 245, 245)},
+ {"yellowgreen", NSVG_RGB(154, 205, 50)},
#endif
};
-static unsigned int nsvg__parseColorName(const char* str)
-{
- int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);
-
- for (i = 0; i < ncolors; i++) {
- if (strcmp(nsvg__colors[i].name, str) == 0) {
- return nsvg__colors[i].color;
- }
- }
-
- return NSVG_RGB(128, 128, 128);
-}
-
-static unsigned int nsvg__parseColor(const char* str)
-{
- size_t len = 0;
- while(*str == ' ') ++str;
- len = strlen(str);
- if (len >= 1 && *str == '#')
- return nsvg__parseColorHex(str);
- else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(')
- return nsvg__parseColorRGB(str);
- return nsvg__parseColorName(str);
-}
-
-static float nsvg__parseOpacity(const char* str)
-{
- float val = nsvg__atof(str);
- if (val < 0.0f) val = 0.0f;
- if (val > 1.0f) val = 1.0f;
- return val;
-}
-
-static float nsvg__parseMiterLimit(const char* str)
-{
- float val = nsvg__atof(str);
- if (val < 0.0f) val = 0.0f;
- return val;
-}
-
-static int nsvg__parseUnits(const char* units)
-{
- if (units[0] == 'p' && units[1] == 'x')
- return NSVG_UNITS_PX;
- else if (units[0] == 'p' && units[1] == 't')
- return NSVG_UNITS_PT;
- else if (units[0] == 'p' && units[1] == 'c')
- return NSVG_UNITS_PC;
- else if (units[0] == 'm' && units[1] == 'm')
- return NSVG_UNITS_MM;
- else if (units[0] == 'c' && units[1] == 'm')
- return NSVG_UNITS_CM;
- else if (units[0] == 'i' && units[1] == 'n')
- return NSVG_UNITS_IN;
- else if (units[0] == '%')
- return NSVG_UNITS_PERCENT;
- else if (units[0] == 'e' && units[1] == 'm')
- return NSVG_UNITS_EM;
- else if (units[0] == 'e' && units[1] == 'x')
- return NSVG_UNITS_EX;
- return NSVG_UNITS_USER;
-}
-
-static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str)
-{
- NSVGcoordinate coord = {0, NSVG_UNITS_USER};
- char buf[64];
- coord.units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64));
- coord.value = nsvg__atof(buf);
- return coord;
-}
-
-static NSVGcoordinate nsvg__coord(float v, int units)
-{
- NSVGcoordinate coord = {v, units};
- return coord;
-}
-
-static float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length)
-{
- NSVGcoordinate coord = nsvg__parseCoordinateRaw(str);
- return nsvg__convertToPixels(p, coord, orig, length);
-}
-
-static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na)
-{
- const char* end;
- const char* ptr;
- char it[64];
-
- *na = 0;
- ptr = str;
- while (*ptr && *ptr != '(') ++ptr;
- if (*ptr == 0)
- return 1;
- end = ptr;
- while (*end && *end != ')') ++end;
- if (*end == 0)
- return 1;
-
- while (ptr < end) {
- if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) {
- if (*na >= maxNa) return 0;
- ptr = nsvg__parseNumber(ptr, it, 64);
- args[(*na)++] = (float)nsvg__atof(it);
- } else {
- ++ptr;
- }
- }
- return (int)(end - str);
-}
-
-
-static int nsvg__parseMatrix(float* xform, const char* str)
-{
- float t[6];
- int na = 0;
- int len = nsvg__parseTransformArgs(str, t, 6, &na);
- if (na != 6) return len;
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseTranslate(float* xform, const char* str)
-{
- float args[2];
- float t[6];
- int na = 0;
- int len = nsvg__parseTransformArgs(str, args, 2, &na);
- if (na == 1) args[1] = 0.0;
-
- nsvg__xformSetTranslation(t, args[0], args[1]);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseScale(float* xform, const char* str)
-{
- float args[2];
- int na = 0;
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 2, &na);
- if (na == 1) args[1] = args[0];
- nsvg__xformSetScale(t, args[0], args[1]);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseSkewX(float* xform, const char* str)
-{
- float args[1];
- int na = 0;
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 1, &na);
- nsvg__xformSetSkewX(t, args[0]/180.0f*NSVG_PI);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseSkewY(float* xform, const char* str)
-{
- float args[1];
- int na = 0;
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 1, &na);
- nsvg__xformSetSkewY(t, args[0]/180.0f*NSVG_PI);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseRotate(float* xform, const char* str)
-{
- float args[3];
- int na = 0;
- float m[6];
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 3, &na);
- if (na == 1)
- args[1] = args[2] = 0.0f;
- nsvg__xformIdentity(m);
-
- if (na > 1) {
- nsvg__xformSetTranslation(t, -args[1], -args[2]);
- nsvg__xformMultiply(m, t);
- }
-
- nsvg__xformSetRotation(t, args[0]/180.0f*NSVG_PI);
- nsvg__xformMultiply(m, t);
-
- if (na > 1) {
- nsvg__xformSetTranslation(t, args[1], args[2]);
- nsvg__xformMultiply(m, t);
- }
-
- memcpy(xform, m, sizeof(float)*6);
-
- return len;
-}
-
-static void nsvg__parseTransform(float* xform, const char* str)
-{
- float t[6];
- nsvg__xformIdentity(xform);
- while (*str)
- {
- if (strncmp(str, "matrix", 6) == 0)
- str += nsvg__parseMatrix(t, str);
- else if (strncmp(str, "translate", 9) == 0)
- str += nsvg__parseTranslate(t, str);
- else if (strncmp(str, "scale", 5) == 0)
- str += nsvg__parseScale(t, str);
- else if (strncmp(str, "rotate", 6) == 0)
- str += nsvg__parseRotate(t, str);
- else if (strncmp(str, "skewX", 5) == 0)
- str += nsvg__parseSkewX(t, str);
- else if (strncmp(str, "skewY", 5) == 0)
- str += nsvg__parseSkewY(t, str);
- else{
- ++str;
- continue;
- }
-
- nsvg__xformPremultiply(xform, t);
- }
-}
-
-static void nsvg__parseUrl(char* id, const char* str)
-{
- int i = 0;
- str += 4; // "url(";
- if (*str == '#')
- str++;
- while (i < 63 && *str != ')') {
- id[i] = *str++;
- i++;
- }
- id[i] = '\0';
-}
-
-static char nsvg__parseLineCap(const char* str)
-{
- if (strcmp(str, "butt") == 0)
- return NSVG_CAP_BUTT;
- else if (strcmp(str, "round") == 0)
- return NSVG_CAP_ROUND;
- else if (strcmp(str, "square") == 0)
- return NSVG_CAP_SQUARE;
- // TODO: handle inherit.
- return NSVG_CAP_BUTT;
-}
-
-static char nsvg__parseLineJoin(const char* str)
-{
- if (strcmp(str, "miter") == 0)
- return NSVG_JOIN_MITER;
- else if (strcmp(str, "round") == 0)
- return NSVG_JOIN_ROUND;
- else if (strcmp(str, "bevel") == 0)
- return NSVG_JOIN_BEVEL;
- // TODO: handle inherit.
- return NSVG_JOIN_MITER;
-}
-
-static char nsvg__parseFillRule(const char* str)
-{
- if (strcmp(str, "nonzero") == 0)
- return NSVG_FILLRULE_NONZERO;
- else if (strcmp(str, "evenodd") == 0)
- return NSVG_FILLRULE_EVENODD;
- // TODO: handle inherit.
- return NSVG_FILLRULE_NONZERO;
-}
-
-static const char* nsvg__getNextDashItem(const char* s, char* it)
-{
- int n = 0;
- it[0] = '\0';
- // Skip white spaces and commas
- while (nsvg__isspace(*s) || *s == ',') s++;
- // Advance until whitespace, comma or end.
- while (*s && (!nsvg__isspace(*s) && *s != ',')) {
- if (n < 63)
- it[n++] = *s;
- s++;
- }
- it[n++] = '\0';
- return s;
-}
-
-static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray)
-{
- char item[64];
- int count = 0, i;
- float sum = 0.0f;
-
- // Handle "none"
- if (str[0] == 'n')
- return 0;
-
- // Parse dashes
- while (*str) {
- str = nsvg__getNextDashItem(str, item);
- if (!*item) break;
- if (count < NSVG_MAX_DASHES)
- strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p)));
- }
-
- for (i = 0; i < count; i++)
- sum += strokeDashArray[i];
- if (sum <= 1e-6f)
- count = 0;
-
- return count;
-}
-
-static void nsvg__parseStyle(NSVGparser* p, const char* str);
-
-static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value)
-{
- float xform[6];
- NSVGattrib* attr = nsvg__getAttr(p);
- if (!attr) return 0;
-
- if (strcmp(name, "style") == 0) {
- nsvg__parseStyle(p, value);
- } else if (strcmp(name, "display") == 0) {
- if (strcmp(value, "none") == 0)
- attr->visible = 0;
- // Don't reset ->visible on display:inline, one display:none hides the whole subtree
-
- } else if (strcmp(name, "fill") == 0) {
- if (strcmp(value, "none") == 0) {
- attr->hasFill = 0;
- } else if (strncmp(value, "url(", 4) == 0) {
- attr->hasFill = 2;
- nsvg__parseUrl(attr->fillGradient, value);
- } else {
- attr->hasFill = 1;
- attr->fillColor = nsvg__parseColor(value);
- }
- } else if (strcmp(name, "opacity") == 0) {
- attr->opacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "fill-opacity") == 0) {
- attr->fillOpacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "stroke") == 0) {
- if (strcmp(value, "none") == 0) {
- attr->hasStroke = 0;
- } else if (strncmp(value, "url(", 4) == 0) {
- attr->hasStroke = 2;
- nsvg__parseUrl(attr->strokeGradient, value);
- } else {
- attr->hasStroke = 1;
- attr->strokeColor = nsvg__parseColor(value);
- }
- } else if (strcmp(name, "stroke-width") == 0) {
- attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
- } else if (strcmp(name, "stroke-dasharray") == 0) {
- attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray);
- } else if (strcmp(name, "stroke-dashoffset") == 0) {
- attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
- } else if (strcmp(name, "stroke-opacity") == 0) {
- attr->strokeOpacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "stroke-linecap") == 0) {
- attr->strokeLineCap = nsvg__parseLineCap(value);
- } else if (strcmp(name, "stroke-linejoin") == 0) {
- attr->strokeLineJoin = nsvg__parseLineJoin(value);
- } else if (strcmp(name, "stroke-miterlimit") == 0) {
- attr->miterLimit = nsvg__parseMiterLimit(value);
- } else if (strcmp(name, "fill-rule") == 0) {
- attr->fillRule = nsvg__parseFillRule(value);
- } else if (strcmp(name, "font-size") == 0) {
- attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
- } else if (strcmp(name, "transform") == 0) {
- nsvg__parseTransform(xform, value);
- nsvg__xformPremultiply(attr->xform, xform);
- } else if (strcmp(name, "stop-color") == 0) {
- attr->stopColor = nsvg__parseColor(value);
- } else if (strcmp(name, "stop-opacity") == 0) {
- attr->stopOpacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "offset") == 0) {
- attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);
- } else if (strcmp(name, "id") == 0) {
- strncpy(attr->id, value, 63);
- attr->id[63] = '\0';
- } else {
- return 0;
- }
- return 1;
-}
-
-static int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end)
-{
- const char* str;
- const char* val;
- char name[512];
- char value[512];
- int n;
-
- str = start;
- while (str < end && *str != ':') ++str;
-
- val = str;
-
- // Right Trim
- while (str > start && (*str == ':' || nsvg__isspace(*str))) --str;
- ++str;
-
- n = (int)(str - start);
- if (n > 511) n = 511;
- if (n) memcpy(name, start, n);
- name[n] = 0;
-
- while (val < end && (*val == ':' || nsvg__isspace(*val))) ++val;
-
- n = (int)(end - val);
- if (n > 511) n = 511;
- if (n) memcpy(value, val, n);
- value[n] = 0;
-
- return nsvg__parseAttr(p, name, value);
-}
-
-static void nsvg__parseStyle(NSVGparser* p, const char* str)
-{
- const char* start;
- const char* end;
-
- while (*str) {
- // Left Trim
- while(nsvg__isspace(*str)) ++str;
- start = str;
- while(*str && *str != ';') ++str;
- end = str;
-
- // Right Trim
- while (end > start && (*end == ';' || nsvg__isspace(*end))) --end;
- ++end;
-
- nsvg__parseNameValue(p, start, end);
- if (*str) ++str;
- }
-}
-
-static void nsvg__parseAttribs(NSVGparser* p, const char** attr)
-{
- int i;
- for (i = 0; attr[i]; i += 2)
- {
- if (strcmp(attr[i], "style") == 0)
- nsvg__parseStyle(p, attr[i + 1]);
- else
- nsvg__parseAttr(p, attr[i], attr[i + 1]);
- }
-}
-
-static int nsvg__getArgsPerElement(char cmd)
-{
- switch (cmd) {
- case 'v':
- case 'V':
- case 'h':
- case 'H':
- return 1;
- case 'm':
- case 'M':
- case 'l':
- case 'L':
- case 't':
- case 'T':
- return 2;
- case 'q':
- case 'Q':
- case 's':
- case 'S':
- return 4;
- case 'c':
- case 'C':
- return 6;
- case 'a':
- case 'A':
- return 7;
- }
- return 0;
-}
-
-static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel) {
- *cpx += args[0];
- *cpy += args[1];
- } else {
- *cpx = args[0];
- *cpy = args[1];
- }
- nsvg__moveTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel) {
- *cpx += args[0];
- *cpy += args[1];
- } else {
- *cpx = args[0];
- *cpy = args[1];
- }
- nsvg__lineTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel)
- *cpx += args[0];
- else
- *cpx = args[0];
- nsvg__lineTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel)
- *cpy += args[0];
- else
- *cpy = args[0];
- nsvg__lineTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x2, y2, cx1, cy1, cx2, cy2;
-
- if (rel) {
- cx1 = *cpx + args[0];
- cy1 = *cpy + args[1];
- cx2 = *cpx + args[2];
- cy2 = *cpy + args[3];
- x2 = *cpx + args[4];
- y2 = *cpy + args[5];
- } else {
- cx1 = args[0];
- cy1 = args[1];
- cx2 = args[2];
- cy2 = args[3];
- x2 = args[4];
- y2 = args[5];
- }
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx2;
- *cpy2 = cy2;
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x1, y1, x2, y2, cx1, cy1, cx2, cy2;
-
- x1 = *cpx;
- y1 = *cpy;
- if (rel) {
- cx2 = *cpx + args[0];
- cy2 = *cpy + args[1];
- x2 = *cpx + args[2];
- y2 = *cpy + args[3];
- } else {
- cx2 = args[0];
- cy2 = args[1];
- x2 = args[2];
- y2 = args[3];
- }
-
- cx1 = 2*x1 - *cpx2;
- cy1 = 2*y1 - *cpy2;
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx2;
- *cpy2 = cy2;
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x1, y1, x2, y2, cx, cy;
- float cx1, cy1, cx2, cy2;
-
- x1 = *cpx;
- y1 = *cpy;
- if (rel) {
- cx = *cpx + args[0];
- cy = *cpy + args[1];
- x2 = *cpx + args[2];
- y2 = *cpy + args[3];
- } else {
- cx = args[0];
- cy = args[1];
- x2 = args[2];
- y2 = args[3];
- }
-
- // Convert to cubic bezier
- cx1 = x1 + 2.0f/3.0f*(cx - x1);
- cy1 = y1 + 2.0f/3.0f*(cy - y1);
- cx2 = x2 + 2.0f/3.0f*(cx - x2);
- cy2 = y2 + 2.0f/3.0f*(cy - y2);
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx;
- *cpy2 = cy;
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x1, y1, x2, y2, cx, cy;
- float cx1, cy1, cx2, cy2;
-
- x1 = *cpx;
- y1 = *cpy;
- if (rel) {
- x2 = *cpx + args[0];
- y2 = *cpy + args[1];
- } else {
- x2 = args[0];
- y2 = args[1];
- }
-
- cx = 2*x1 - *cpx2;
- cy = 2*y1 - *cpy2;
-
- // Convert to cubix bezier
- cx1 = x1 + 2.0f/3.0f*(cx - x1);
- cy1 = y1 + 2.0f/3.0f*(cy - y1);
- cx2 = x2 + 2.0f/3.0f*(cx - x2);
- cy2 = y2 + 2.0f/3.0f*(cy - y2);
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx;
- *cpy2 = cy;
- *cpx = x2;
- *cpy = y2;
-}
-
-static float nsvg__sqr(float x) { return x*x; }
-static float nsvg__vmag(float x, float y) { return sqrtf(x*x + y*y); }
-
-static float nsvg__vecrat(float ux, float uy, float vx, float vy)
-{
- return (ux*vx + uy*vy) / (nsvg__vmag(ux,uy) * nsvg__vmag(vx,vy));
-}
-
-static float nsvg__vecang(float ux, float uy, float vx, float vy)
-{
- float r = nsvg__vecrat(ux,uy, vx,vy);
- if (r < -1.0f) r = -1.0f;
- if (r > 1.0f) r = 1.0f;
- return ((ux*vy < uy*vx) ? -1.0f : 1.0f) * acosf(r);
-}
-
-static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- // Ported from canvg (https://code.google.com/p/canvg/)
- float rx, ry, rotx;
- float x1, y1, x2, y2, cx, cy, dx, dy, d;
- float x1p, y1p, cxp, cyp, s, sa, sb;
- float ux, uy, vx, vy, a1, da;
- float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6];
- float sinrx, cosrx;
- int fa, fs;
- int i, ndivs;
- float hda, kappa;
-
- rx = fabsf(args[0]); // y radius
- ry = fabsf(args[1]); // x radius
- rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle
- fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc
- fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction
- x1 = *cpx; // start point
- y1 = *cpy;
- if (rel) { // end point
- x2 = *cpx + args[5];
- y2 = *cpy + args[6];
- } else {
- x2 = args[5];
- y2 = args[6];
- }
-
- dx = x1 - x2;
- dy = y1 - y2;
- d = sqrtf(dx*dx + dy*dy);
- if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) {
- // The arc degenerates to a line
- nsvg__lineTo(p, x2, y2);
- *cpx = x2;
- *cpy = y2;
- return;
- }
-
- sinrx = sinf(rotx);
- cosrx = cosf(rotx);
-
- // Convert to center point parameterization.
- // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
- // 1) Compute x1', y1'
- x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f;
- y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f;
- d = nsvg__sqr(x1p)/nsvg__sqr(rx) + nsvg__sqr(y1p)/nsvg__sqr(ry);
- if (d > 1) {
- d = sqrtf(d);
- rx *= d;
- ry *= d;
- }
- // 2) Compute cx', cy'
- s = 0.0f;
- sa = nsvg__sqr(rx)*nsvg__sqr(ry) - nsvg__sqr(rx)*nsvg__sqr(y1p) - nsvg__sqr(ry)*nsvg__sqr(x1p);
- sb = nsvg__sqr(rx)*nsvg__sqr(y1p) + nsvg__sqr(ry)*nsvg__sqr(x1p);
- if (sa < 0.0f) sa = 0.0f;
- if (sb > 0.0f)
- s = sqrtf(sa / sb);
- if (fa == fs)
- s = -s;
- cxp = s * rx * y1p / ry;
- cyp = s * -ry * x1p / rx;
-
- // 3) Compute cx,cy from cx',cy'
- cx = (x1 + x2)/2.0f + cosrx*cxp - sinrx*cyp;
- cy = (y1 + y2)/2.0f + sinrx*cxp + cosrx*cyp;
-
- // 4) Calculate theta1, and delta theta.
- ux = (x1p - cxp) / rx;
- uy = (y1p - cyp) / ry;
- vx = (-x1p - cxp) / rx;
- vy = (-y1p - cyp) / ry;
- a1 = nsvg__vecang(1.0f,0.0f, ux,uy); // Initial angle
- da = nsvg__vecang(ux,uy, vx,vy); // Delta angle
-
-// if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI;
-// if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0;
-
- if (fs == 0 && da > 0)
- da -= 2 * NSVG_PI;
- else if (fs == 1 && da < 0)
- da += 2 * NSVG_PI;
-
- // Approximate the arc using cubic spline segments.
- t[0] = cosrx; t[1] = sinrx;
- t[2] = -sinrx; t[3] = cosrx;
- t[4] = cx; t[5] = cy;
-
- // Split arc into max 90 degree segments.
- // The loop assumes an iteration per end point (including start and end), this +1.
- ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f);
- hda = (da / (float)ndivs) / 2.0f;
- kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda));
- if (da < 0.0f)
- kappa = -kappa;
-
- for (i = 0; i <= ndivs; i++) {
- a = a1 + da * ((float)i/(float)ndivs);
- dx = cosf(a);
- dy = sinf(a);
- nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); // position
- nsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); // tangent
- if (i > 0)
- nsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y);
- px = x;
- py = y;
- ptanx = tanx;
- ptany = tany;
- }
-
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__parsePath(NSVGparser* p, const char** attr)
-{
- const char* s = NULL;
- char cmd = '\0';
- float args[10];
- int nargs;
- int rargs = 0;
- float cpx, cpy, cpx2, cpy2;
- const char* tmp[4];
- char closedFlag;
- int i;
- char item[64];
-
- for (i = 0; attr[i]; i += 2) {
- if (strcmp(attr[i], "d") == 0) {
- s = attr[i + 1];
- } else {
- tmp[0] = attr[i];
- tmp[1] = attr[i + 1];
- tmp[2] = 0;
- tmp[3] = 0;
- nsvg__parseAttribs(p, tmp);
- }
- }
-
- if (s) {
- nsvg__resetPath(p);
- cpx = 0; cpy = 0;
- cpx2 = 0; cpy2 = 0;
- closedFlag = 0;
- nargs = 0;
-
- while (*s) {
- item[0] = '\0';
- if ((cmd == 'A' || cmd == 'a') && (nargs == 3 || nargs == 4))
- s = nsvg__getNextPathItemWhenArcFlag(s, item);
- if (!*item)
- s = nsvg__getNextPathItem(s, item);
- if (!*item) break;
- if (nsvg__isnum(item[0])) {
- if (nargs < 10)
- args[nargs++] = (float)nsvg__atof(item);
- if (nargs >= rargs) {
- switch (cmd) {
- case 'm':
- case 'M':
- nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);
- // Moveto can be followed by multiple coordinate pairs,
- // which should be treated as linetos.
- cmd = (cmd == 'm') ? 'l' : 'L';
- rargs = nsvg__getArgsPerElement(cmd);
- cpx2 = cpx; cpy2 = cpy;
- break;
- case 'l':
- case 'L':
- nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- case 'H':
- case 'h':
- nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- case 'V':
- case 'v':
- nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- case 'C':
- case 'c':
- nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
- break;
- case 'S':
- case 's':
- nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
- break;
- case 'Q':
- case 'q':
- nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
- break;
- case 'T':
- case 't':
- nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0);
- break;
- case 'A':
- case 'a':
- nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- default:
- if (nargs >= 2) {
- cpx = args[nargs-2];
- cpy = args[nargs-1];
- cpx2 = cpx; cpy2 = cpy;
- }
- break;
- }
- nargs = 0;
- }
- } else {
- // New command
- if (nargs) {
- NANOSVG_DEBUG("unfinished command '%c' %d/%d args\n", cmd, nargs, rargs);
- }
- cmd = item[0];
- rargs = nsvg__getArgsPerElement(cmd);
- if (cmd == 'M' || cmd == 'm') {
- // Commit path.
- if (p->npts > 0)
- nsvg__addPath(p, closedFlag);
- // Start new subpath.
- nsvg__resetPath(p);
- closedFlag = 0;
- nargs = 0;
- } else if (cmd == 'Z' || cmd == 'z') {
- closedFlag = 1;
- // Commit path.
- if (p->npts > 0) {
- // Move current point to first point
- cpx = p->pts[0];
- cpy = p->pts[1];
- cpx2 = cpx; cpy2 = cpy;
- nsvg__addPath(p, closedFlag);
- }
- // Start new subpath.
- nsvg__resetPath(p);
- nsvg__moveTo(p, cpx, cpy);
- closedFlag = 0;
- nargs = 0;
- }
- }
- }
- // Commit path.
- if (p->npts)
- nsvg__addPath(p, closedFlag);
- }
-
- nsvg__addShape(p);
-}
-
-static void nsvg__parseRect(NSVGparser* p, const char** attr)
-{
- float x = 0.0f;
- float y = 0.0f;
- float w = 0.0f;
- float h = 0.0f;
- float rx = -1.0f; // marks not set
- float ry = -1.0f;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "width") == 0) w = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p));
- if (strcmp(attr[i], "height") == 0) h = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p));
- if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
- if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
- }
- }
-
- if (rx < 0.0f && ry > 0.0f) rx = ry;
- if (ry < 0.0f && rx > 0.0f) ry = rx;
- if (rx < 0.0f) rx = 0.0f;
- if (ry < 0.0f) ry = 0.0f;
- if (rx > w/2.0f) rx = w/2.0f;
- if (ry > h/2.0f) ry = h/2.0f;
-
- if (w != 0.0f && h != 0.0f) {
- nsvg__resetPath(p);
-
- if (rx < 0.00001f || ry < 0.0001f) {
- nsvg__moveTo(p, x, y);
- nsvg__lineTo(p, x+w, y);
- nsvg__lineTo(p, x+w, y+h);
- nsvg__lineTo(p, x, y+h);
- } else {
- // Rounded rectangle
- nsvg__moveTo(p, x+rx, y);
- nsvg__lineTo(p, x+w-rx, y);
- nsvg__cubicBezTo(p, x+w-rx*(1-NSVG_KAPPA90), y, x+w, y+ry*(1-NSVG_KAPPA90), x+w, y+ry);
- nsvg__lineTo(p, x+w, y+h-ry);
- nsvg__cubicBezTo(p, x+w, y+h-ry*(1-NSVG_KAPPA90), x+w-rx*(1-NSVG_KAPPA90), y+h, x+w-rx, y+h);
- nsvg__lineTo(p, x+rx, y+h);
- nsvg__cubicBezTo(p, x+rx*(1-NSVG_KAPPA90), y+h, x, y+h-ry*(1-NSVG_KAPPA90), x, y+h-ry);
- nsvg__lineTo(p, x, y+ry);
- nsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y);
- }
-
- nsvg__addPath(p, 1);
-
- nsvg__addShape(p);
- }
-}
-
-static void nsvg__parseCircle(NSVGparser* p, const char** attr)
-{
- float cx = 0.0f;
- float cy = 0.0f;
- float r = 0.0f;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "r") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p)));
- }
- }
-
- if (r > 0.0f) {
- nsvg__resetPath(p);
-
- nsvg__moveTo(p, cx+r, cy);
- nsvg__cubicBezTo(p, cx+r, cy+r*NSVG_KAPPA90, cx+r*NSVG_KAPPA90, cy+r, cx, cy+r);
- nsvg__cubicBezTo(p, cx-r*NSVG_KAPPA90, cy+r, cx-r, cy+r*NSVG_KAPPA90, cx-r, cy);
- nsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r);
- nsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy);
-
- nsvg__addPath(p, 1);
-
- nsvg__addShape(p);
- }
-}
-
-static void nsvg__parseEllipse(NSVGparser* p, const char** attr)
-{
- float cx = 0.0f;
- float cy = 0.0f;
- float rx = 0.0f;
- float ry = 0.0f;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
- if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
- }
- }
-
- if (rx > 0.0f && ry > 0.0f) {
-
- nsvg__resetPath(p);
-
- nsvg__moveTo(p, cx+rx, cy);
- nsvg__cubicBezTo(p, cx+rx, cy+ry*NSVG_KAPPA90, cx+rx*NSVG_KAPPA90, cy+ry, cx, cy+ry);
- nsvg__cubicBezTo(p, cx-rx*NSVG_KAPPA90, cy+ry, cx-rx, cy+ry*NSVG_KAPPA90, cx-rx, cy);
- nsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry);
- nsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy);
-
- nsvg__addPath(p, 1);
-
- nsvg__addShape(p);
- }
-}
-
-static void nsvg__parseLine(NSVGparser* p, const char** attr)
-{
- float x1 = 0.0;
- float y1 = 0.0;
- float x2 = 0.0;
- float y2 = 0.0;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "x1") == 0) x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "y1") == 0) y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "x2") == 0) x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "y2") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- }
- }
-
- nsvg__resetPath(p);
-
- nsvg__moveTo(p, x1, y1);
- nsvg__lineTo(p, x2, y2);
-
- nsvg__addPath(p, 0);
-
- nsvg__addShape(p);
-}
-
-static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag)
-{
- int i;
- const char* s;
- float args[2];
- int nargs, npts = 0;
- char item[64];
-
- nsvg__resetPath(p);
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "points") == 0) {
- s = attr[i + 1];
- nargs = 0;
- while (*s) {
- s = nsvg__getNextPathItem(s, item);
- args[nargs++] = (float)nsvg__atof(item);
- if (nargs >= 2) {
- if (npts == 0)
- nsvg__moveTo(p, args[0], args[1]);
- else
- nsvg__lineTo(p, args[0], args[1]);
- nargs = 0;
- npts++;
- }
- }
- }
- }
- }
-
- nsvg__addPath(p, (char)closeFlag);
-
- nsvg__addShape(p);
-}
-
-static void nsvg__parseSVG(NSVGparser* p, const char** attr)
-{
- int i;
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "width") == 0) {
- p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
- } else if (strcmp(attr[i], "height") == 0) {
- p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
- } else if (strcmp(attr[i], "viewBox") == 0) {
- const char *s = attr[i + 1];
- char buf[64];
- s = nsvg__parseNumber(s, buf, 64);
- p->viewMinx = nsvg__atof(buf);
- while (nsvg__isspace(*s) || *s == '%' || *s == ',') s++;
- if (!*s) return;
- s = nsvg__parseNumber(s, buf, 64);
- p->viewMiny = nsvg__atof(buf);
- while (nsvg__isspace(*s) || *s == '%' || *s == ',') s++;
- if (!*s) return;
- s = nsvg__parseNumber(s, buf, 64);
- p->viewWidth = nsvg__atof(buf);
- while (nsvg__isspace(*s) || *s == '%' || *s == ',') s++;
- if (!*s) return;
- s = nsvg__parseNumber(s, buf, 64);
- p->viewHeight = nsvg__atof(buf);
- } else if (strcmp(attr[i], "preserveAspectRatio") == 0) {
- if (strstr(attr[i + 1], "none") != 0) {
- // No uniform scaling
- p->alignType = NSVG_ALIGN_NONE;
- } else {
- // Parse X align
- if (strstr(attr[i + 1], "xMin") != 0)
- p->alignX = NSVG_ALIGN_MIN;
- else if (strstr(attr[i + 1], "xMid") != 0)
- p->alignX = NSVG_ALIGN_MID;
- else if (strstr(attr[i + 1], "xMax") != 0)
- p->alignX = NSVG_ALIGN_MAX;
- // Parse X align
- if (strstr(attr[i + 1], "yMin") != 0)
- p->alignY = NSVG_ALIGN_MIN;
- else if (strstr(attr[i + 1], "yMid") != 0)
- p->alignY = NSVG_ALIGN_MID;
- else if (strstr(attr[i + 1], "yMax") != 0)
- p->alignY = NSVG_ALIGN_MAX;
- // Parse meet/slice
- p->alignType = NSVG_ALIGN_MEET;
- if (strstr(attr[i + 1], "slice") != 0)
- p->alignType = NSVG_ALIGN_SLICE;
- }
- }
- }
- }
-}
-
-static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type)
-{
- int i;
- NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData));
- if (grad == NULL) return;
- memset(grad, 0, sizeof(NSVGgradientData));
- grad->units = NSVG_OBJECT_SPACE;
- grad->type = type;
- if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) {
- grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
- grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
- grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT);
- grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
- } else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) {
- grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
- grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
- grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
- }
-
- nsvg__xformIdentity(grad->xform);
-
- for (i = 0; attr[i]; i += 2) {
- if (strcmp(attr[i], "id") == 0) {
- strncpy(grad->id, attr[i+1], 63);
- grad->id[63] = '\0';
- } else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "gradientUnits") == 0) {
- if (strcmp(attr[i+1], "objectBoundingBox") == 0)
- grad->units = NSVG_OBJECT_SPACE;
- else
- grad->units = NSVG_USER_SPACE;
- } else if (strcmp(attr[i], "gradientTransform") == 0) {
- nsvg__parseTransform(grad->xform, attr[i + 1]);
- } else if (strcmp(attr[i], "cx") == 0) {
- grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "cy") == 0) {
- grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "r") == 0) {
- grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "fx") == 0) {
- grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "fy") == 0) {
- grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "x1") == 0) {
- grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "y1") == 0) {
- grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "x2") == 0) {
- grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "y2") == 0) {
- grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "spreadMethod") == 0) {
- if (strcmp(attr[i+1], "pad") == 0)
- grad->spread = NSVG_SPREAD_PAD;
- else if (strcmp(attr[i+1], "reflect") == 0)
- grad->spread = NSVG_SPREAD_REFLECT;
- else if (strcmp(attr[i+1], "repeat") == 0)
- grad->spread = NSVG_SPREAD_REPEAT;
- } else if (strcmp(attr[i], "xlink:href") == 0) {
- const char *href = attr[i+1];
- strncpy(grad->ref, href+1, 62);
- grad->ref[62] = '\0';
- }
- }
- }
-
- grad->next = p->gradients;
- p->gradients = grad;
-}
-
-static void nsvg__parseGradientStop(NSVGparser* p, const char** attr)
-{
- NSVGattrib* curAttr = nsvg__getAttr(p);
- NSVGgradientData* grad;
- NSVGgradientStop* stop;
- int i, idx;
-
- curAttr->stopOffset = 0;
- curAttr->stopColor = 0;
- curAttr->stopOpacity = 1.0f;
-
- for (i = 0; attr[i]; i += 2) {
- nsvg__parseAttr(p, attr[i], attr[i + 1]);
- }
-
- // Add stop to the last gradient.
- grad = p->gradients;
- if (grad == NULL) return;
-
- grad->nstops++;
- grad->stops = (NSVGgradientStop*)realloc(grad->stops, sizeof(NSVGgradientStop)*grad->nstops);
- if (grad->stops == NULL) return;
-
- // Insert
- idx = grad->nstops-1;
- for (i = 0; i < grad->nstops-1; i++) {
- if (curAttr->stopOffset < grad->stops[i].offset) {
- idx = i;
- break;
- }
- }
- if (idx != grad->nstops-1) {
- for (i = grad->nstops-1; i > idx; i--)
- grad->stops[i] = grad->stops[i-1];
- }
-
- stop = &grad->stops[idx];
- stop->color = curAttr->stopColor;
- stop->color |= (unsigned int)(curAttr->stopOpacity*255) << 24;
- stop->offset = curAttr->stopOffset;
-}
-
-static void nsvg__startElement(void* ud, const char* el, const char** attr)
-{
- NSVGparser* p = (NSVGparser*)ud;
-
- if (p->defsFlag) {
- // Skip everything but gradients in defs
- if (strcmp(el, "linearGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
- } else if (strcmp(el, "radialGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
- } else if (strcmp(el, "stop") == 0) {
- nsvg__parseGradientStop(p, attr);
- }
- return;
- }
-
- if (strcmp(el, "g") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseAttribs(p, attr);
- } else if (strcmp(el, "path") == 0) {
- if (p->pathFlag) // Do not allow nested paths.
- return;
- nsvg__pushAttr(p);
- nsvg__parsePath(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "rect") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseRect(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "circle") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseCircle(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "ellipse") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseEllipse(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "line") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseLine(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "polyline") == 0) {
- nsvg__pushAttr(p);
- nsvg__parsePoly(p, attr, 0);
- nsvg__popAttr(p);
- } else if (strcmp(el, "polygon") == 0) {
- nsvg__pushAttr(p);
- nsvg__parsePoly(p, attr, 1);
- nsvg__popAttr(p);
- } else if (strcmp(el, "linearGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
- } else if (strcmp(el, "radialGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
- } else if (strcmp(el, "stop") == 0) {
- nsvg__parseGradientStop(p, attr);
- } else if (strcmp(el, "defs") == 0) {
- p->defsFlag = 1;
- } else if (strcmp(el, "svg") == 0) {
- nsvg__parseSVG(p, attr);
- }
-}
-
-static void nsvg__endElement(void* ud, const char* el)
-{
- NSVGparser* p = (NSVGparser*)ud;
-
- if (strcmp(el, "g") == 0) {
- nsvg__popAttr(p);
- } else if (strcmp(el, "path") == 0) {
- p->pathFlag = 0;
- } else if (strcmp(el, "defs") == 0) {
- p->defsFlag = 0;
- }
-}
-
-static void nsvg__content(void* ud, const char* s)
-{
- NSVG_NOTUSED(ud);
- NSVG_NOTUSED(s);
- // empty
-}
-
-static void nsvg__imageBounds(NSVGparser* p, float* bounds)
-{
- NSVGshape* shape;
- shape = p->image->shapes;
- if (shape == NULL) {
- bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
- return;
- }
- bounds[0] = shape->bounds[0];
- bounds[1] = shape->bounds[1];
- bounds[2] = shape->bounds[2];
- bounds[3] = shape->bounds[3];
- for (shape = shape->next; shape != NULL; shape = shape->next) {
- bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]);
- bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]);
- bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]);
- bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]);
- }
-}
-
-static float nsvg__viewAlign(float content, float container, int type)
-{
- if (type == NSVG_ALIGN_MIN)
- return 0;
- else if (type == NSVG_ALIGN_MAX)
- return container - content;
- // mid
- return (container - content) * 0.5f;
-}
-
-static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy)
-{
- float t[6];
- nsvg__xformSetTranslation(t, tx, ty);
- nsvg__xformMultiply (grad->xform, t);
-
- nsvg__xformSetScale(t, sx, sy);
- nsvg__xformMultiply (grad->xform, t);
-}
-
-static void nsvg__scaleToViewbox(NSVGparser* p, const char* units)
-{
- NSVGshape* shape;
- NSVGpath* path;
- float tx, ty, sx, sy, us, bounds[4], t[6], avgs;
- int i;
- float* pt;
-
- // Guess image size if not set completely.
- nsvg__imageBounds(p, bounds);
-
- if (p->viewWidth == 0) {
- if (p->image->width > 0) {
- p->viewWidth = p->image->width;
- } else {
- p->viewMinx = bounds[0];
- p->viewWidth = bounds[2] - bounds[0];
- }
- }
- if (p->viewHeight == 0) {
- if (p->image->height > 0) {
- p->viewHeight = p->image->height;
- } else {
- p->viewMiny = bounds[1];
- p->viewHeight = bounds[3] - bounds[1];
- }
- }
- if (p->image->width == 0)
- p->image->width = p->viewWidth;
- if (p->image->height == 0)
- p->image->height = p->viewHeight;
-
- tx = -p->viewMinx;
- ty = -p->viewMiny;
- sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0;
- sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0;
- // Unit scaling
- us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f);
-
- // Fix aspect ratio
- if (p->alignType == NSVG_ALIGN_MEET) {
- // fit whole image into viewbox
- sx = sy = nsvg__minf(sx, sy);
- tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;
- ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;
- } else if (p->alignType == NSVG_ALIGN_SLICE) {
- // fill whole viewbox with image
- sx = sy = nsvg__maxf(sx, sy);
- tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;
- ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;
- }
-
- // Transform
- sx *= us;
- sy *= us;
- avgs = (sx+sy) / 2.0f;
- for (shape = p->image->shapes; shape != NULL; shape = shape->next) {
- shape->bounds[0] = (shape->bounds[0] + tx) * sx;
- shape->bounds[1] = (shape->bounds[1] + ty) * sy;
- shape->bounds[2] = (shape->bounds[2] + tx) * sx;
- shape->bounds[3] = (shape->bounds[3] + ty) * sy;
- for (path = shape->paths; path != NULL; path = path->next) {
- path->bounds[0] = (path->bounds[0] + tx) * sx;
- path->bounds[1] = (path->bounds[1] + ty) * sy;
- path->bounds[2] = (path->bounds[2] + tx) * sx;
- path->bounds[3] = (path->bounds[3] + ty) * sy;
- for (i =0; i < path->npts; i++) {
- pt = &path->pts[i*2];
- pt[0] = (pt[0] + tx) * sx;
- pt[1] = (pt[1] + ty) * sy;
- }
- }
-
- if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) {
- nsvg__scaleGradient(shape->fill.gradient, tx,ty, sx,sy);
- memcpy(t, shape->fill.gradient->xform, sizeof(float)*6);
- nsvg__xformInverse(shape->fill.gradient->xform, t);
- }
- if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) {
- nsvg__scaleGradient(shape->stroke.gradient, tx,ty, sx,sy);
- memcpy(t, shape->stroke.gradient->xform, sizeof(float)*6);
- nsvg__xformInverse(shape->stroke.gradient->xform, t);
- }
-
- shape->strokeWidth *= avgs;
- shape->strokeDashOffset *= avgs;
- for (i = 0; i < shape->strokeDashCount; i++)
- shape->strokeDashArray[i] *= avgs;
- }
-}
-
-NSVGimage* nsvgParse(char* input, const char* units, float dpi)
-{
- NSVGparser* p;
- NSVGimage* ret = 0;
-
- p = nsvg__createParser();
- if (p == NULL) {
- return NULL;
- }
- p->dpi = dpi;
-
- nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
-
- // Scale to viewBox
- nsvg__scaleToViewbox(p, units);
-
- ret = p->image;
- p->image = NULL;
-
- nsvg__deleteParser(p);
-
- return ret;
-}
-
-NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
-{
- FILE* fp = NULL;
- size_t size;
- char* data = NULL;
- NSVGimage* image = NULL;
-
- fp = fopen(filename, "rb");
- if (!fp) goto error;
- fseek(fp, 0, SEEK_END);
- size = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- data = (char*)malloc(size+1);
- if (data == NULL) goto error;
- if (fread(data, 1, size, fp) != size) goto error;
- data[size] = '\0'; // Must be null terminated.
- fclose(fp);
- image = nsvgParse(data, units, dpi);
- free(data);
-
- return image;
+static unsigned int nsvg__parseColorName(const char *str) {
+ int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);
+
+ for (i = 0; i < ncolors; i++) {
+ if (strcmp(nsvg__colors[i].name, str) == 0) {
+ return nsvg__colors[i].color;
+ }
+ }
+
+ return NSVG_RGB(128, 128, 128);
+}
+
+static unsigned int nsvg__parseColor(const char *str) {
+ size_t len = 0;
+ while (*str == ' ')
+ ++str;
+ len = strlen(str);
+ if (len >= 1 && *str == '#')
+ return nsvg__parseColorHex(str);
+ else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(')
+ return nsvg__parseColorRGB(str);
+ return nsvg__parseColorName(str);
+}
+
+static float nsvg__parseOpacity(const char *str) {
+ float val = nsvg__atof(str);
+ if (val < 0.0f)
+ val = 0.0f;
+ if (val > 1.0f)
+ val = 1.0f;
+ return val;
+}
+
+static float nsvg__parseMiterLimit(const char *str) {
+ float val = nsvg__atof(str);
+ if (val < 0.0f)
+ val = 0.0f;
+ return val;
+}
+
+static int nsvg__parseUnits(const char *units) {
+ if (units[0] == 'p' && units[1] == 'x')
+ return NSVG_UNITS_PX;
+ else if (units[0] == 'p' && units[1] == 't')
+ return NSVG_UNITS_PT;
+ else if (units[0] == 'p' && units[1] == 'c')
+ return NSVG_UNITS_PC;
+ else if (units[0] == 'm' && units[1] == 'm')
+ return NSVG_UNITS_MM;
+ else if (units[0] == 'c' && units[1] == 'm')
+ return NSVG_UNITS_CM;
+ else if (units[0] == 'i' && units[1] == 'n')
+ return NSVG_UNITS_IN;
+ else if (units[0] == '%')
+ return NSVG_UNITS_PERCENT;
+ else if (units[0] == 'e' && units[1] == 'm')
+ return NSVG_UNITS_EM;
+ else if (units[0] == 'e' && units[1] == 'x')
+ return NSVG_UNITS_EX;
+ return NSVG_UNITS_USER;
+}
+
+static NSVGcoordinate nsvg__parseCoordinateRaw(const char *str) {
+ NSVGcoordinate coord = {0, NSVG_UNITS_USER};
+ char buf[64];
+ coord.units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64));
+ coord.value = nsvg__atof(buf);
+ return coord;
+}
+
+static NSVGcoordinate nsvg__coord(float v, int units) {
+ NSVGcoordinate coord = {v, units};
+ return coord;
+}
+
+static float nsvg__parseCoordinate(NSVGparser *p, const char *str, float orig, float length) {
+ NSVGcoordinate coord = nsvg__parseCoordinateRaw(str);
+ return nsvg__convertToPixels(p, coord, orig, length);
+}
+
+static int nsvg__parseTransformArgs(const char *str, float *args, int maxNa, int *na) {
+ const char *end;
+ const char *ptr;
+ char it[64];
+
+ *na = 0;
+ ptr = str;
+ while (*ptr && *ptr != '(')
+ ++ptr;
+ if (*ptr == 0)
+ return 1;
+ end = ptr;
+ while (*end && *end != ')')
+ ++end;
+ if (*end == 0)
+ return 1;
+
+ while (ptr < end) {
+ if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) {
+ if (*na >= maxNa)
+ return 0;
+ ptr = nsvg__parseNumber(ptr, it, 64);
+ args[(*na)++] = (float)nsvg__atof(it);
+ } else {
+ ++ptr;
+ }
+ }
+ return (int)(end - str);
+}
+
+static int nsvg__parseMatrix(float *xform, const char *str) {
+ float t[6];
+ int na = 0;
+ int len = nsvg__parseTransformArgs(str, t, 6, &na);
+ if (na != 6)
+ return len;
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseTranslate(float *xform, const char *str) {
+ float args[2];
+ float t[6];
+ int na = 0;
+ int len = nsvg__parseTransformArgs(str, args, 2, &na);
+ if (na == 1)
+ args[1] = 0.0;
+
+ nsvg__xformSetTranslation(t, args[0], args[1]);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseScale(float *xform, const char *str) {
+ float args[2];
+ int na = 0;
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 2, &na);
+ if (na == 1)
+ args[1] = args[0];
+ nsvg__xformSetScale(t, args[0], args[1]);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseSkewX(float *xform, const char *str) {
+ float args[1];
+ int na = 0;
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 1, &na);
+ nsvg__xformSetSkewX(t, args[0] / 180.0f * NSVG_PI);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseSkewY(float *xform, const char *str) {
+ float args[1];
+ int na = 0;
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 1, &na);
+ nsvg__xformSetSkewY(t, args[0] / 180.0f * NSVG_PI);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseRotate(float *xform, const char *str) {
+ float args[3];
+ int na = 0;
+ float m[6];
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 3, &na);
+ if (na == 1)
+ args[1] = args[2] = 0.0f;
+ nsvg__xformIdentity(m);
+
+ if (na > 1) {
+ nsvg__xformSetTranslation(t, -args[1], -args[2]);
+ nsvg__xformMultiply(m, t);
+ }
+
+ nsvg__xformSetRotation(t, args[0] / 180.0f * NSVG_PI);
+ nsvg__xformMultiply(m, t);
+
+ if (na > 1) {
+ nsvg__xformSetTranslation(t, args[1], args[2]);
+ nsvg__xformMultiply(m, t);
+ }
+
+ memcpy(xform, m, sizeof(float) * 6);
+
+ return len;
+}
+
+static void nsvg__parseTransform(float *xform, const char *str) {
+ float t[6];
+ nsvg__xformIdentity(xform);
+ while (*str) {
+ if (strncmp(str, "matrix", 6) == 0)
+ str += nsvg__parseMatrix(t, str);
+ else if (strncmp(str, "translate", 9) == 0)
+ str += nsvg__parseTranslate(t, str);
+ else if (strncmp(str, "scale", 5) == 0)
+ str += nsvg__parseScale(t, str);
+ else if (strncmp(str, "rotate", 6) == 0)
+ str += nsvg__parseRotate(t, str);
+ else if (strncmp(str, "skewX", 5) == 0)
+ str += nsvg__parseSkewX(t, str);
+ else if (strncmp(str, "skewY", 5) == 0)
+ str += nsvg__parseSkewY(t, str);
+ else {
+ ++str;
+ continue;
+ }
+
+ nsvg__xformPremultiply(xform, t);
+ }
+}
+
+static void nsvg__parseUrl(char *id, const char *str) {
+ int i = 0;
+ str += 4; // "url(";
+ if (*str == '#')
+ str++;
+ while (i < 63 && *str != ')') {
+ id[i] = *str++;
+ i++;
+ }
+ id[i] = '\0';
+}
+
+static char nsvg__parseLineCap(const char *str) {
+ if (strcmp(str, "butt") == 0)
+ return NSVG_CAP_BUTT;
+ else if (strcmp(str, "round") == 0)
+ return NSVG_CAP_ROUND;
+ else if (strcmp(str, "square") == 0)
+ return NSVG_CAP_SQUARE;
+ // TODO: handle inherit.
+ return NSVG_CAP_BUTT;
+}
+
+static char nsvg__parseLineJoin(const char *str) {
+ if (strcmp(str, "miter") == 0)
+ return NSVG_JOIN_MITER;
+ else if (strcmp(str, "round") == 0)
+ return NSVG_JOIN_ROUND;
+ else if (strcmp(str, "bevel") == 0)
+ return NSVG_JOIN_BEVEL;
+ // TODO: handle inherit.
+ return NSVG_JOIN_MITER;
+}
+
+static char nsvg__parseFillRule(const char *str) {
+ if (strcmp(str, "nonzero") == 0)
+ return NSVG_FILLRULE_NONZERO;
+ else if (strcmp(str, "evenodd") == 0)
+ return NSVG_FILLRULE_EVENODD;
+ // TODO: handle inherit.
+ return NSVG_FILLRULE_NONZERO;
+}
+
+static const char *nsvg__getNextDashItem(const char *s, char *it) {
+ int n = 0;
+ it[0] = '\0';
+ // Skip white spaces and commas
+ while (nsvg__isspace(*s) || *s == ',')
+ s++;
+ // Advance until whitespace, comma or end.
+ while (*s && (!nsvg__isspace(*s) && *s != ',')) {
+ if (n < 63)
+ it[n++] = *s;
+ s++;
+ }
+ it[n++] = '\0';
+ return s;
+}
+
+static int nsvg__parseStrokeDashArray(NSVGparser *p, const char *str, float *strokeDashArray) {
+ char item[64];
+ int count = 0, i;
+ float sum = 0.0f;
+
+ // Handle "none"
+ if (str[0] == 'n')
+ return 0;
+
+ // Parse dashes
+ while (*str) {
+ str = nsvg__getNextDashItem(str, item);
+ if (!*item)
+ break;
+ if (count < NSVG_MAX_DASHES)
+ strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p)));
+ }
+
+ for (i = 0; i < count; i++)
+ sum += strokeDashArray[i];
+ if (sum <= 1e-6f)
+ count = 0;
+
+ return count;
+}
+
+static void nsvg__parseStyle(NSVGparser *p, const char *str);
+
+static int nsvg__parseAttr(NSVGparser *p, const char *name, const char *value) {
+ float xform[6];
+ NSVGattrib *attr = nsvg__getAttr(p);
+ if (!attr)
+ return 0;
+
+ if (strcmp(name, "style") == 0) {
+ nsvg__parseStyle(p, value);
+ } else if (strcmp(name, "display") == 0) {
+ if (strcmp(value, "none") == 0)
+ attr->visible = 0;
+ // Don't reset ->visible on display:inline, one display:none hides the whole subtree
+
+ } else if (strcmp(name, "fill") == 0) {
+ if (strcmp(value, "none") == 0) {
+ attr->hasFill = 0;
+ } else if (strncmp(value, "url(", 4) == 0) {
+ attr->hasFill = 2;
+ nsvg__parseUrl(attr->fillGradient, value);
+ } else {
+ attr->hasFill = 1;
+ attr->fillColor = nsvg__parseColor(value);
+ }
+ } else if (strcmp(name, "opacity") == 0) {
+ attr->opacity = nsvg__parseOpacity(value);
+ } else if (strcmp(name, "fill-opacity") == 0) {
+ attr->fillOpacity = nsvg__parseOpacity(value);
+ } else if (strcmp(name, "stroke") == 0) {
+ if (strcmp(value, "none") == 0) {
+ attr->hasStroke = 0;
+ } else if (strncmp(value, "url(", 4) == 0) {
+ attr->hasStroke = 2;
+ nsvg__parseUrl(attr->strokeGradient, value);
+ } else {
+ attr->hasStroke = 1;
+ attr->strokeColor = nsvg__parseColor(value);
+ }
+ } else if (strcmp(name, "stroke-width") == 0) {
+ attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
+ } else if (strcmp(name, "stroke-dasharray") == 0) {
+ attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray);
+ } else if (strcmp(name, "stroke-dashoffset") == 0) {
+ attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
+ } else if (strcmp(name, "stroke-opacity") == 0) {
+ attr->strokeOpacity = nsvg__parseOpacity(value);
+ } else if (strcmp(name, "stroke-linecap") == 0) {
+ attr->strokeLineCap = nsvg__parseLineCap(value);
+ } else if (strcmp(name, "stroke-linejoin") == 0) {
+ attr->strokeLineJoin = nsvg__parseLineJoin(value);
+ } else if (strcmp(name, "stroke-miterlimit") == 0) {
+ attr->miterLimit = nsvg__parseMiterLimit(value);
+ } else if (strcmp(name, "fill-rule") == 0) {
+ attr->fillRule = nsvg__parseFillRule(value);
+ } else if (strcmp(name, "font-size") == 0) {
+ attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
+ } else if (strcmp(name, "transform") == 0) {
+ nsvg__parseTransform(xform, value);
+ nsvg__xformPremultiply(attr->xform, xform);
+ } else if (strcmp(name, "stop-color") == 0) {
+ attr->stopColor = nsvg__parseColor(value);
+ } else if (strcmp(name, "stop-opacity") == 0) {
+ attr->stopOpacity = nsvg__parseOpacity(value);
+ } else if (strcmp(name, "offset") == 0) {
+ attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);
+ } else if (strcmp(name, "id") == 0) {
+ strncpy(attr->id, value, 63);
+ attr->id[63] = '\0';
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static int nsvg__parseNameValue(NSVGparser *p, const char *start, const char *end) {
+ const char *str;
+ const char *val;
+ char name[512];
+ char value[512];
+ int n;
+
+ str = start;
+ while (str < end && *str != ':')
+ ++str;
+
+ val = str;
+
+ // Right Trim
+ while (str > start && (*str == ':' || nsvg__isspace(*str)))
+ --str;
+ ++str;
+
+ n = (int)(str - start);
+ if (n > 511)
+ n = 511;
+ if (n)
+ memcpy(name, start, n);
+ name[n] = 0;
+
+ while (val < end && (*val == ':' || nsvg__isspace(*val)))
+ ++val;
+
+ n = (int)(end - val);
+ if (n > 511)
+ n = 511;
+ if (n)
+ memcpy(value, val, n);
+ value[n] = 0;
+
+ return nsvg__parseAttr(p, name, value);
+}
+
+static void nsvg__parseStyle(NSVGparser *p, const char *str) {
+ const char *start;
+ const char *end;
+
+ while (*str) {
+ // Left Trim
+ while (nsvg__isspace(*str))
+ ++str;
+ start = str;
+ while (*str && *str != ';')
+ ++str;
+ end = str;
+
+ // Right Trim
+ while (end > start && (*end == ';' || nsvg__isspace(*end)))
+ --end;
+ ++end;
+
+ nsvg__parseNameValue(p, start, end);
+ if (*str)
+ ++str;
+ }
+}
+
+static void nsvg__parseAttribs(NSVGparser *p, const char **attr) {
+ int i;
+ for (i = 0; attr[i]; i += 2) {
+ if (strcmp(attr[i], "style") == 0)
+ nsvg__parseStyle(p, attr[i + 1]);
+ else
+ nsvg__parseAttr(p, attr[i], attr[i + 1]);
+ }
+}
+
+static int nsvg__getArgsPerElement(char cmd) {
+ switch (cmd) {
+ case 'v':
+ case 'V':
+ case 'h':
+ case 'H':
+ return 1;
+ case 'm':
+ case 'M':
+ case 'l':
+ case 'L':
+ case 't':
+ case 'T':
+ return 2;
+ case 'q':
+ case 'Q':
+ case 's':
+ case 'S':
+ return 4;
+ case 'c':
+ case 'C':
+ return 6;
+ case 'a':
+ case 'A':
+ return 7;
+ }
+ return 0;
+}
+
+static void nsvg__pathMoveTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+ if (rel) {
+ *cpx += args[0];
+ *cpy += args[1];
+ } else {
+ *cpx = args[0];
+ *cpy = args[1];
+ }
+ nsvg__moveTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathLineTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+ if (rel) {
+ *cpx += args[0];
+ *cpy += args[1];
+ } else {
+ *cpx = args[0];
+ *cpy = args[1];
+ }
+ nsvg__lineTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathHLineTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+ if (rel)
+ *cpx += args[0];
+ else
+ *cpx = args[0];
+ nsvg__lineTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathVLineTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+ if (rel)
+ *cpy += args[0];
+ else
+ *cpy = args[0];
+ nsvg__lineTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathCubicBezTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+ int rel) {
+ float x2, y2, cx1, cy1, cx2, cy2;
+
+ if (rel) {
+ cx1 = *cpx + args[0];
+ cy1 = *cpy + args[1];
+ cx2 = *cpx + args[2];
+ cy2 = *cpy + args[3];
+ x2 = *cpx + args[4];
+ y2 = *cpy + args[5];
+ } else {
+ cx1 = args[0];
+ cy1 = args[1];
+ cx2 = args[2];
+ cy2 = args[3];
+ x2 = args[4];
+ y2 = args[5];
+ }
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx2;
+ *cpy2 = cy2;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__pathCubicBezShortTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+ int rel) {
+ float x1, y1, x2, y2, cx1, cy1, cx2, cy2;
+
+ x1 = *cpx;
+ y1 = *cpy;
+ if (rel) {
+ cx2 = *cpx + args[0];
+ cy2 = *cpy + args[1];
+ x2 = *cpx + args[2];
+ y2 = *cpy + args[3];
+ } else {
+ cx2 = args[0];
+ cy2 = args[1];
+ x2 = args[2];
+ y2 = args[3];
+ }
+
+ cx1 = 2 * x1 - *cpx2;
+ cy1 = 2 * y1 - *cpy2;
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx2;
+ *cpy2 = cy2;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__pathQuadBezTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args, int rel) {
+ float x1, y1, x2, y2, cx, cy;
+ float cx1, cy1, cx2, cy2;
+
+ x1 = *cpx;
+ y1 = *cpy;
+ if (rel) {
+ cx = *cpx + args[0];
+ cy = *cpy + args[1];
+ x2 = *cpx + args[2];
+ y2 = *cpy + args[3];
+ } else {
+ cx = args[0];
+ cy = args[1];
+ x2 = args[2];
+ y2 = args[3];
+ }
+
+ // Convert to cubic bezier
+ cx1 = x1 + 2.0f / 3.0f * (cx - x1);
+ cy1 = y1 + 2.0f / 3.0f * (cy - y1);
+ cx2 = x2 + 2.0f / 3.0f * (cx - x2);
+ cy2 = y2 + 2.0f / 3.0f * (cy - y2);
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx;
+ *cpy2 = cy;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__pathQuadBezShortTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+ int rel) {
+ float x1, y1, x2, y2, cx, cy;
+ float cx1, cy1, cx2, cy2;
+
+ x1 = *cpx;
+ y1 = *cpy;
+ if (rel) {
+ x2 = *cpx + args[0];
+ y2 = *cpy + args[1];
+ } else {
+ x2 = args[0];
+ y2 = args[1];
+ }
+
+ cx = 2 * x1 - *cpx2;
+ cy = 2 * y1 - *cpy2;
+
+ // Convert to cubix bezier
+ cx1 = x1 + 2.0f / 3.0f * (cx - x1);
+ cy1 = y1 + 2.0f / 3.0f * (cy - y1);
+ cx2 = x2 + 2.0f / 3.0f * (cx - x2);
+ cy2 = y2 + 2.0f / 3.0f * (cy - y2);
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx;
+ *cpy2 = cy;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static float nsvg__sqr(float x) { return x * x; }
+static float nsvg__vmag(float x, float y) { return sqrtf(x * x + y * y); }
+
+static float nsvg__vecrat(float ux, float uy, float vx, float vy) {
+ return (ux * vx + uy * vy) / (nsvg__vmag(ux, uy) * nsvg__vmag(vx, vy));
+}
+
+static float nsvg__vecang(float ux, float uy, float vx, float vy) {
+ float r = nsvg__vecrat(ux, uy, vx, vy);
+ if (r < -1.0f)
+ r = -1.0f;
+ if (r > 1.0f)
+ r = 1.0f;
+ return ((ux * vy < uy * vx) ? -1.0f : 1.0f) * acosf(r);
+}
+
+static void nsvg__pathArcTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+ // Ported from canvg (https://code.google.com/p/canvg/)
+ float rx, ry, rotx;
+ float x1, y1, x2, y2, cx, cy, dx, dy, d;
+ float x1p, y1p, cxp, cyp, s, sa, sb;
+ float ux, uy, vx, vy, a1, da;
+ float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6];
+ float sinrx, cosrx;
+ int fa, fs;
+ int i, ndivs;
+ float hda, kappa;
+
+ rx = fabsf(args[0]); // y radius
+ ry = fabsf(args[1]); // x radius
+ rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle
+ fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc
+ fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction
+ x1 = *cpx; // start point
+ y1 = *cpy;
+ if (rel) { // end point
+ x2 = *cpx + args[5];
+ y2 = *cpy + args[6];
+ } else {
+ x2 = args[5];
+ y2 = args[6];
+ }
+
+ dx = x1 - x2;
+ dy = y1 - y2;
+ d = sqrtf(dx * dx + dy * dy);
+ if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) {
+ // The arc degenerates to a line
+ nsvg__lineTo(p, x2, y2);
+ *cpx = x2;
+ *cpy = y2;
+ return;
+ }
+
+ sinrx = sinf(rotx);
+ cosrx = cosf(rotx);
+
+ // Convert to center point parameterization.
+ // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
+ // 1) Compute x1', y1'
+ x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f;
+ y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f;
+ d = nsvg__sqr(x1p) / nsvg__sqr(rx) + nsvg__sqr(y1p) / nsvg__sqr(ry);
+ if (d > 1) {
+ d = sqrtf(d);
+ rx *= d;
+ ry *= d;
+ }
+ // 2) Compute cx', cy'
+ s = 0.0f;
+ sa = nsvg__sqr(rx) * nsvg__sqr(ry) - nsvg__sqr(rx) * nsvg__sqr(y1p) - nsvg__sqr(ry) * nsvg__sqr(x1p);
+ sb = nsvg__sqr(rx) * nsvg__sqr(y1p) + nsvg__sqr(ry) * nsvg__sqr(x1p);
+ if (sa < 0.0f)
+ sa = 0.0f;
+ if (sb > 0.0f)
+ s = sqrtf(sa / sb);
+ if (fa == fs)
+ s = -s;
+ cxp = s * rx * y1p / ry;
+ cyp = s * -ry * x1p / rx;
+
+ // 3) Compute cx,cy from cx',cy'
+ cx = (x1 + x2) / 2.0f + cosrx * cxp - sinrx * cyp;
+ cy = (y1 + y2) / 2.0f + sinrx * cxp + cosrx * cyp;
+
+ // 4) Calculate theta1, and delta theta.
+ ux = (x1p - cxp) / rx;
+ uy = (y1p - cyp) / ry;
+ vx = (-x1p - cxp) / rx;
+ vy = (-y1p - cyp) / ry;
+ a1 = nsvg__vecang(1.0f, 0.0f, ux, uy); // Initial angle
+ da = nsvg__vecang(ux, uy, vx, vy); // Delta angle
+
+ // if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI;
+ // if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0;
+
+ if (fs == 0 && da > 0)
+ da -= 2 * NSVG_PI;
+ else if (fs == 1 && da < 0)
+ da += 2 * NSVG_PI;
+
+ // Approximate the arc using cubic spline segments.
+ t[0] = cosrx;
+ t[1] = sinrx;
+ t[2] = -sinrx;
+ t[3] = cosrx;
+ t[4] = cx;
+ t[5] = cy;
+
+ // Split arc into max 90 degree segments.
+ // The loop assumes an iteration per end point (including start and end), this +1.
+ ndivs = (int)(fabsf(da) / (NSVG_PI * 0.5f) + 1.0f);
+ hda = (da / (float)ndivs) / 2.0f;
+ kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda));
+ if (da < 0.0f)
+ kappa = -kappa;
+
+ for (i = 0; i <= ndivs; i++) {
+ a = a1 + da * ((float)i / (float)ndivs);
+ dx = cosf(a);
+ dy = sinf(a);
+ nsvg__xformPoint(&x, &y, dx * rx, dy * ry, t); // position
+ nsvg__xformVec(&tanx, &tany, -dy * rx * kappa, dx * ry * kappa, t); // tangent
+ if (i > 0)
+ nsvg__cubicBezTo(p, px + ptanx, py + ptany, x - tanx, y - tany, x, y);
+ px = x;
+ py = y;
+ ptanx = tanx;
+ ptany = tany;
+ }
+
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__parsePath(NSVGparser *p, const char **attr) {
+ const char *s = NULL;
+ char cmd = '\0';
+ float args[10];
+ int nargs;
+ int rargs = 0;
+ float cpx, cpy, cpx2, cpy2;
+ const char *tmp[4];
+ char closedFlag;
+ int i;
+ char item[64];
+
+ for (i = 0; attr[i]; i += 2) {
+ if (strcmp(attr[i], "d") == 0) {
+ s = attr[i + 1];
+ } else {
+ tmp[0] = attr[i];
+ tmp[1] = attr[i + 1];
+ tmp[2] = 0;
+ tmp[3] = 0;
+ nsvg__parseAttribs(p, tmp);
+ }
+ }
+
+ if (s) {
+ nsvg__resetPath(p);
+ cpx = 0;
+ cpy = 0;
+ cpx2 = 0;
+ cpy2 = 0;
+ closedFlag = 0;
+ nargs = 0;
+
+ while (*s) {
+ item[0] = '\0';
+ if ((cmd == 'A' || cmd == 'a') && (nargs == 3 || nargs == 4))
+ s = nsvg__getNextPathItemWhenArcFlag(s, item);
+ if (!*item)
+ s = nsvg__getNextPathItem(s, item);
+ if (!*item)
+ break;
+ if (nsvg__isnum(item[0])) {
+ if (nargs < 10)
+ args[nargs++] = (float)nsvg__atof(item);
+ if (nargs >= rargs) {
+ switch (cmd) {
+ case 'm':
+ case 'M':
+ nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);
+ // Moveto can be followed by multiple coordinate pairs,
+ // which should be treated as linetos.
+ cmd = (cmd == 'm') ? 'l' : 'L';
+ rargs = nsvg__getArgsPerElement(cmd);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ case 'l':
+ case 'L':
+ nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ case 'H':
+ case 'h':
+ nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ case 'V':
+ case 'v':
+ nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ case 'C':
+ case 'c':
+ nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
+ break;
+ case 'S':
+ case 's':
+ nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
+ break;
+ case 'Q':
+ case 'q':
+ nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
+ break;
+ case 'T':
+ case 't':
+ nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0);
+ break;
+ case 'A':
+ case 'a':
+ nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ default:
+ if (nargs >= 2) {
+ cpx = args[nargs - 2];
+ cpy = args[nargs - 1];
+ cpx2 = cpx;
+ cpy2 = cpy;
+ }
+ break;
+ }
+ nargs = 0;
+ }
+ } else {
+ // New command
+ if (nargs) {
+ NANOSVG_DEBUG("unfinished command '%c' %d/%d args\n", cmd, nargs, rargs);
+ }
+ cmd = item[0];
+ rargs = nsvg__getArgsPerElement(cmd);
+ if (cmd == 'M' || cmd == 'm') {
+ // Commit path.
+ if (p->npts > 0)
+ nsvg__addPath(p, closedFlag);
+ // Start new subpath.
+ nsvg__resetPath(p);
+ closedFlag = 0;
+ nargs = 0;
+ } else if (cmd == 'Z' || cmd == 'z') {
+ closedFlag = 1;
+ // Commit path.
+ if (p->npts > 0) {
+ // Move current point to first point
+ cpx = p->pts[0];
+ cpy = p->pts[1];
+ cpx2 = cpx;
+ cpy2 = cpy;
+ nsvg__addPath(p, closedFlag);
+ }
+ // Start new subpath.
+ nsvg__resetPath(p);
+ nsvg__moveTo(p, cpx, cpy);
+ closedFlag = 0;
+ nargs = 0;
+ }
+ }
+ }
+ // Commit path.
+ if (p->npts)
+ nsvg__addPath(p, closedFlag);
+ }
+
+ nsvg__addShape(p);
+}
+
+static void nsvg__parseRect(NSVGparser *p, const char **attr) {
+ float x = 0.0f;
+ float y = 0.0f;
+ float w = 0.0f;
+ float h = 0.0f;
+ float rx = -1.0f; // marks not set
+ float ry = -1.0f;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "x") == 0)
+ x = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "y") == 0)
+ y = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "width") == 0)
+ w = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p));
+ if (strcmp(attr[i], "height") == 0)
+ h = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p));
+ if (strcmp(attr[i], "rx") == 0)
+ rx = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p)));
+ if (strcmp(attr[i], "ry") == 0)
+ ry = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p)));
+ }
+ }
+
+ if (rx < 0.0f && ry > 0.0f)
+ rx = ry;
+ if (ry < 0.0f && rx > 0.0f)
+ ry = rx;
+ if (rx < 0.0f)
+ rx = 0.0f;
+ if (ry < 0.0f)
+ ry = 0.0f;
+ if (rx > w / 2.0f)
+ rx = w / 2.0f;
+ if (ry > h / 2.0f)
+ ry = h / 2.0f;
+
+ if (w != 0.0f && h != 0.0f) {
+ nsvg__resetPath(p);
+
+ if (rx < 0.00001f || ry < 0.0001f) {
+ nsvg__moveTo(p, x, y);
+ nsvg__lineTo(p, x + w, y);
+ nsvg__lineTo(p, x + w, y + h);
+ nsvg__lineTo(p, x, y + h);
+ } else {
+ // Rounded rectangle
+ nsvg__moveTo(p, x + rx, y);
+ nsvg__lineTo(p, x + w - rx, y);
+ nsvg__cubicBezTo(p, x + w - rx * (1 - NSVG_KAPPA90), y, x + w, y + ry * (1 - NSVG_KAPPA90), x + w, y + ry);
+ nsvg__lineTo(p, x + w, y + h - ry);
+ nsvg__cubicBezTo(p, x + w, y + h - ry * (1 - NSVG_KAPPA90), x + w - rx * (1 - NSVG_KAPPA90), y + h,
+ x + w - rx, y + h);
+ nsvg__lineTo(p, x + rx, y + h);
+ nsvg__cubicBezTo(p, x + rx * (1 - NSVG_KAPPA90), y + h, x, y + h - ry * (1 - NSVG_KAPPA90), x, y + h - ry);
+ nsvg__lineTo(p, x, y + ry);
+ nsvg__cubicBezTo(p, x, y + ry * (1 - NSVG_KAPPA90), x + rx * (1 - NSVG_KAPPA90), y, x + rx, y);
+ }
+
+ nsvg__addPath(p, 1);
+
+ nsvg__addShape(p);
+ }
+}
+
+static void nsvg__parseCircle(NSVGparser *p, const char **attr) {
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float r = 0.0f;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "cx") == 0)
+ cx = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "cy") == 0)
+ cy = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "r") == 0)
+ r = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualLength(p)));
+ }
+ }
+
+ if (r > 0.0f) {
+ nsvg__resetPath(p);
+
+ nsvg__moveTo(p, cx + r, cy);
+ nsvg__cubicBezTo(p, cx + r, cy + r * NSVG_KAPPA90, cx + r * NSVG_KAPPA90, cy + r, cx, cy + r);
+ nsvg__cubicBezTo(p, cx - r * NSVG_KAPPA90, cy + r, cx - r, cy + r * NSVG_KAPPA90, cx - r, cy);
+ nsvg__cubicBezTo(p, cx - r, cy - r * NSVG_KAPPA90, cx - r * NSVG_KAPPA90, cy - r, cx, cy - r);
+ nsvg__cubicBezTo(p, cx + r * NSVG_KAPPA90, cy - r, cx + r, cy - r * NSVG_KAPPA90, cx + r, cy);
+
+ nsvg__addPath(p, 1);
+
+ nsvg__addShape(p);
+ }
+}
+
+static void nsvg__parseEllipse(NSVGparser *p, const char **attr) {
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float rx = 0.0f;
+ float ry = 0.0f;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "cx") == 0)
+ cx = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "cy") == 0)
+ cy = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "rx") == 0)
+ rx = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p)));
+ if (strcmp(attr[i], "ry") == 0)
+ ry = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p)));
+ }
+ }
+
+ if (rx > 0.0f && ry > 0.0f) {
+
+ nsvg__resetPath(p);
+
+ nsvg__moveTo(p, cx + rx, cy);
+ nsvg__cubicBezTo(p, cx + rx, cy + ry * NSVG_KAPPA90, cx + rx * NSVG_KAPPA90, cy + ry, cx, cy + ry);
+ nsvg__cubicBezTo(p, cx - rx * NSVG_KAPPA90, cy + ry, cx - rx, cy + ry * NSVG_KAPPA90, cx - rx, cy);
+ nsvg__cubicBezTo(p, cx - rx, cy - ry * NSVG_KAPPA90, cx - rx * NSVG_KAPPA90, cy - ry, cx, cy - ry);
+ nsvg__cubicBezTo(p, cx + rx * NSVG_KAPPA90, cy - ry, cx + rx, cy - ry * NSVG_KAPPA90, cx + rx, cy);
+
+ nsvg__addPath(p, 1);
+
+ nsvg__addShape(p);
+ }
+}
+
+static void nsvg__parseLine(NSVGparser *p, const char **attr) {
+ float x1 = 0.0;
+ float y1 = 0.0;
+ float x2 = 0.0;
+ float y2 = 0.0;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "x1") == 0)
+ x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "y1") == 0)
+ y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "x2") == 0)
+ x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "y2") == 0)
+ y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ }
+ }
+
+ nsvg__resetPath(p);
+
+ nsvg__moveTo(p, x1, y1);
+ nsvg__lineTo(p, x2, y2);
+
+ nsvg__addPath(p, 0);
+
+ nsvg__addShape(p);
+}
+
+static void nsvg__parsePoly(NSVGparser *p, const char **attr, int closeFlag) {
+ int i;
+ const char *s;
+ float args[2];
+ int nargs, npts = 0;
+ char item[64];
+
+ nsvg__resetPath(p);
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "points") == 0) {
+ s = attr[i + 1];
+ nargs = 0;
+ while (*s) {
+ s = nsvg__getNextPathItem(s, item);
+ args[nargs++] = (float)nsvg__atof(item);
+ if (nargs >= 2) {
+ if (npts == 0)
+ nsvg__moveTo(p, args[0], args[1]);
+ else
+ nsvg__lineTo(p, args[0], args[1]);
+ nargs = 0;
+ npts++;
+ }
+ }
+ }
+ }
+ }
+
+ nsvg__addPath(p, (char)closeFlag);
+
+ nsvg__addShape(p);
+}
+
+static void nsvg__parseSVG(NSVGparser *p, const char **attr) {
+ int i;
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "width") == 0) {
+ p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
+ } else if (strcmp(attr[i], "height") == 0) {
+ p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
+ } else if (strcmp(attr[i], "viewBox") == 0) {
+ const char *s = attr[i + 1];
+ char buf[64];
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewMinx = nsvg__atof(buf);
+ while (nsvg__isspace(*s) || *s == '%' || *s == ',')
+ s++;
+ if (!*s)
+ return;
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewMiny = nsvg__atof(buf);
+ while (nsvg__isspace(*s) || *s == '%' || *s == ',')
+ s++;
+ if (!*s)
+ return;
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewWidth = nsvg__atof(buf);
+ while (nsvg__isspace(*s) || *s == '%' || *s == ',')
+ s++;
+ if (!*s)
+ return;
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewHeight = nsvg__atof(buf);
+ } else if (strcmp(attr[i], "preserveAspectRatio") == 0) {
+ if (strstr(attr[i + 1], "none") != 0) {
+ // No uniform scaling
+ p->alignType = NSVG_ALIGN_NONE;
+ } else {
+ // Parse X align
+ if (strstr(attr[i + 1], "xMin") != 0)
+ p->alignX = NSVG_ALIGN_MIN;
+ else if (strstr(attr[i + 1], "xMid") != 0)
+ p->alignX = NSVG_ALIGN_MID;
+ else if (strstr(attr[i + 1], "xMax") != 0)
+ p->alignX = NSVG_ALIGN_MAX;
+ // Parse X align
+ if (strstr(attr[i + 1], "yMin") != 0)
+ p->alignY = NSVG_ALIGN_MIN;
+ else if (strstr(attr[i + 1], "yMid") != 0)
+ p->alignY = NSVG_ALIGN_MID;
+ else if (strstr(attr[i + 1], "yMax") != 0)
+ p->alignY = NSVG_ALIGN_MAX;
+ // Parse meet/slice
+ p->alignType = NSVG_ALIGN_MEET;
+ if (strstr(attr[i + 1], "slice") != 0)
+ p->alignType = NSVG_ALIGN_SLICE;
+ }
+ }
+ }
+ }
+}
+
+static void nsvg__parseGradient(NSVGparser *p, const char **attr, char type) {
+ int i;
+ NSVGgradientData *grad = (NSVGgradientData *)malloc(sizeof(NSVGgradientData));
+ if (grad == NULL)
+ return;
+ memset(grad, 0, sizeof(NSVGgradientData));
+ grad->units = NSVG_OBJECT_SPACE;
+ grad->type = type;
+ if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) {
+ grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
+ grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
+ grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT);
+ grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
+ } else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) {
+ grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
+ grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
+ grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
+ }
+
+ nsvg__xformIdentity(grad->xform);
+
+ for (i = 0; attr[i]; i += 2) {
+ if (strcmp(attr[i], "id") == 0) {
+ strncpy(grad->id, attr[i + 1], 63);
+ grad->id[63] = '\0';
+ } else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "gradientUnits") == 0) {
+ if (strcmp(attr[i + 1], "objectBoundingBox") == 0)
+ grad->units = NSVG_OBJECT_SPACE;
+ else
+ grad->units = NSVG_USER_SPACE;
+ } else if (strcmp(attr[i], "gradientTransform") == 0) {
+ nsvg__parseTransform(grad->xform, attr[i + 1]);
+ } else if (strcmp(attr[i], "cx") == 0) {
+ grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "cy") == 0) {
+ grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "r") == 0) {
+ grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "fx") == 0) {
+ grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "fy") == 0) {
+ grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "x1") == 0) {
+ grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "y1") == 0) {
+ grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "x2") == 0) {
+ grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "y2") == 0) {
+ grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "spreadMethod") == 0) {
+ if (strcmp(attr[i + 1], "pad") == 0)
+ grad->spread = NSVG_SPREAD_PAD;
+ else if (strcmp(attr[i + 1], "reflect") == 0)
+ grad->spread = NSVG_SPREAD_REFLECT;
+ else if (strcmp(attr[i + 1], "repeat") == 0)
+ grad->spread = NSVG_SPREAD_REPEAT;
+ } else if (strcmp(attr[i], "xlink:href") == 0) {
+ const char *href = attr[i + 1];
+ strncpy(grad->ref, href + 1, 62);
+ grad->ref[62] = '\0';
+ }
+ }
+ }
+
+ grad->next = p->gradients;
+ p->gradients = grad;
+}
+
+static void nsvg__parseGradientStop(NSVGparser *p, const char **attr) {
+ NSVGattrib *curAttr = nsvg__getAttr(p);
+ NSVGgradientData *grad;
+ NSVGgradientStop *stop;
+ int i, idx;
+
+ curAttr->stopOffset = 0;
+ curAttr->stopColor = 0;
+ curAttr->stopOpacity = 1.0f;
+
+ for (i = 0; attr[i]; i += 2) {
+ nsvg__parseAttr(p, attr[i], attr[i + 1]);
+ }
+
+ // Add stop to the last gradient.
+ grad = p->gradients;
+ if (grad == NULL)
+ return;
+
+ grad->nstops++;
+ grad->stops = (NSVGgradientStop *)realloc(grad->stops, sizeof(NSVGgradientStop) * grad->nstops);
+ if (grad->stops == NULL)
+ return;
+
+ // Insert
+ idx = grad->nstops - 1;
+ for (i = 0; i < grad->nstops - 1; i++) {
+ if (curAttr->stopOffset < grad->stops[i].offset) {
+ idx = i;
+ break;
+ }
+ }
+ if (idx != grad->nstops - 1) {
+ for (i = grad->nstops - 1; i > idx; i--)
+ grad->stops[i] = grad->stops[i - 1];
+ }
+
+ stop = &grad->stops[idx];
+ stop->color = curAttr->stopColor;
+ stop->color |= (unsigned int)(curAttr->stopOpacity * 255) << 24;
+ stop->offset = curAttr->stopOffset;
+}
+
+static void nsvg__startElement(void *ud, const char *el, const char **attr) {
+ NSVGparser *p = (NSVGparser *)ud;
+
+ if (p->defsFlag) {
+ // Skip everything but gradients in defs
+ if (strcmp(el, "linearGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
+ } else if (strcmp(el, "radialGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
+ } else if (strcmp(el, "stop") == 0) {
+ nsvg__parseGradientStop(p, attr);
+ }
+ return;
+ }
+
+ if (strcmp(el, "g") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseAttribs(p, attr);
+ } else if (strcmp(el, "path") == 0) {
+ if (p->pathFlag) // Do not allow nested paths.
+ return;
+ nsvg__pushAttr(p);
+ nsvg__parsePath(p, attr);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "rect") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseRect(p, attr);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "circle") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseCircle(p, attr);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "ellipse") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseEllipse(p, attr);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "line") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseLine(p, attr);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "polyline") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parsePoly(p, attr, 0);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "polygon") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parsePoly(p, attr, 1);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "linearGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
+ } else if (strcmp(el, "radialGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
+ } else if (strcmp(el, "stop") == 0) {
+ nsvg__parseGradientStop(p, attr);
+ } else if (strcmp(el, "defs") == 0) {
+ p->defsFlag = 1;
+ } else if (strcmp(el, "svg") == 0) {
+ nsvg__parseSVG(p, attr);
+ }
+}
+
+static void nsvg__endElement(void *ud, const char *el) {
+ NSVGparser *p = (NSVGparser *)ud;
+
+ if (strcmp(el, "g") == 0) {
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "path") == 0) {
+ p->pathFlag = 0;
+ } else if (strcmp(el, "defs") == 0) {
+ p->defsFlag = 0;
+ }
+}
+
+static void nsvg__content(void *ud, const char *s) {
+ NSVG_NOTUSED(ud);
+ NSVG_NOTUSED(s);
+ // empty
+}
+
+static void nsvg__imageBounds(NSVGparser *p, float *bounds) {
+ NSVGshape *shape;
+ shape = p->image->shapes;
+ if (shape == NULL) {
+ bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
+ return;
+ }
+ bounds[0] = shape->bounds[0];
+ bounds[1] = shape->bounds[1];
+ bounds[2] = shape->bounds[2];
+ bounds[3] = shape->bounds[3];
+ for (shape = shape->next; shape != NULL; shape = shape->next) {
+ bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]);
+ bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]);
+ bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]);
+ bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]);
+ }
+}
+
+static float nsvg__viewAlign(float content, float container, int type) {
+ if (type == NSVG_ALIGN_MIN)
+ return 0;
+ else if (type == NSVG_ALIGN_MAX)
+ return container - content;
+ // mid
+ return (container - content) * 0.5f;
+}
+
+static void nsvg__scaleGradient(NSVGgradient *grad, float tx, float ty, float sx, float sy) {
+ float t[6];
+ nsvg__xformSetTranslation(t, tx, ty);
+ nsvg__xformMultiply(grad->xform, t);
+
+ nsvg__xformSetScale(t, sx, sy);
+ nsvg__xformMultiply(grad->xform, t);
+}
+
+static void nsvg__scaleToViewbox(NSVGparser *p, const char *units) {
+ NSVGshape *shape;
+ NSVGpath *path;
+ float tx, ty, sx, sy, us, bounds[4], t[6], avgs;
+ int i;
+ float *pt;
+
+ // Guess image size if not set completely.
+ nsvg__imageBounds(p, bounds);
+
+ if (p->viewWidth == 0) {
+ if (p->image->width > 0) {
+ p->viewWidth = p->image->width;
+ } else {
+ p->viewMinx = bounds[0];
+ p->viewWidth = bounds[2] - bounds[0];
+ }
+ }
+ if (p->viewHeight == 0) {
+ if (p->image->height > 0) {
+ p->viewHeight = p->image->height;
+ } else {
+ p->viewMiny = bounds[1];
+ p->viewHeight = bounds[3] - bounds[1];
+ }
+ }
+ if (p->image->width == 0)
+ p->image->width = p->viewWidth;
+ if (p->image->height == 0)
+ p->image->height = p->viewHeight;
+
+ tx = -p->viewMinx;
+ ty = -p->viewMiny;
+ sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0;
+ sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0;
+ // Unit scaling
+ us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f);
+
+ // Fix aspect ratio
+ if (p->alignType == NSVG_ALIGN_MEET) {
+ // fit whole image into viewbox
+ sx = sy = nsvg__minf(sx, sy);
+ tx += nsvg__viewAlign(p->viewWidth * sx, p->image->width, p->alignX) / sx;
+ ty += nsvg__viewAlign(p->viewHeight * sy, p->image->height, p->alignY) / sy;
+ } else if (p->alignType == NSVG_ALIGN_SLICE) {
+ // fill whole viewbox with image
+ sx = sy = nsvg__maxf(sx, sy);
+ tx += nsvg__viewAlign(p->viewWidth * sx, p->image->width, p->alignX) / sx;
+ ty += nsvg__viewAlign(p->viewHeight * sy, p->image->height, p->alignY) / sy;
+ }
+
+ // Transform
+ sx *= us;
+ sy *= us;
+ avgs = (sx + sy) / 2.0f;
+ for (shape = p->image->shapes; shape != NULL; shape = shape->next) {
+ shape->bounds[0] = (shape->bounds[0] + tx) * sx;
+ shape->bounds[1] = (shape->bounds[1] + ty) * sy;
+ shape->bounds[2] = (shape->bounds[2] + tx) * sx;
+ shape->bounds[3] = (shape->bounds[3] + ty) * sy;
+ for (path = shape->paths; path != NULL; path = path->next) {
+ path->bounds[0] = (path->bounds[0] + tx) * sx;
+ path->bounds[1] = (path->bounds[1] + ty) * sy;
+ path->bounds[2] = (path->bounds[2] + tx) * sx;
+ path->bounds[3] = (path->bounds[3] + ty) * sy;
+ for (i = 0; i < path->npts; i++) {
+ pt = &path->pts[i * 2];
+ pt[0] = (pt[0] + tx) * sx;
+ pt[1] = (pt[1] + ty) * sy;
+ }
+ }
+
+ if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) {
+ nsvg__scaleGradient(shape->fill.gradient, tx, ty, sx, sy);
+ memcpy(t, shape->fill.gradient->xform, sizeof(float) * 6);
+ nsvg__xformInverse(shape->fill.gradient->xform, t);
+ }
+ if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) {
+ nsvg__scaleGradient(shape->stroke.gradient, tx, ty, sx, sy);
+ memcpy(t, shape->stroke.gradient->xform, sizeof(float) * 6);
+ nsvg__xformInverse(shape->stroke.gradient->xform, t);
+ }
+
+ shape->strokeWidth *= avgs;
+ shape->strokeDashOffset *= avgs;
+ for (i = 0; i < shape->strokeDashCount; i++)
+ shape->strokeDashArray[i] *= avgs;
+ }
+}
+
+NSVGimage *nsvgParse(char *input, const char *units, float dpi) {
+ NSVGparser *p;
+ NSVGimage *ret = 0;
+
+ p = nsvg__createParser();
+ if (p == NULL) {
+ return NULL;
+ }
+ p->dpi = dpi;
+
+ nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
+
+ // Scale to viewBox
+ nsvg__scaleToViewbox(p, units);
+
+ ret = p->image;
+ p->image = NULL;
+
+ nsvg__deleteParser(p);
+
+ return ret;
+}
+
+NSVGimage *nsvgParseFromFile(const char *filename, const char *units, float dpi) {
+ FILE *fp = NULL;
+ size_t size;
+ char *data = NULL;
+ NSVGimage *image = NULL;
+
+ fp = fopen(filename, "rb");
+ if (!fp)
+ goto error;
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ data = (char *)malloc(size + 1);
+ if (data == NULL)
+ goto error;
+ if (fread(data, 1, size, fp) != size)
+ goto error;
+ data[size] = '\0'; // Must be null terminated.
+ fclose(fp);
+ image = nsvgParse(data, units, dpi);
+ free(data);
+
+ return image;
error:
- if (fp) fclose(fp);
- if (data) free(data);
- if (image) nsvgDelete(image);
- return NULL;
+ if (fp)
+ fclose(fp);
+ if (data)
+ free(data);
+ if (image)
+ nsvgDelete(image);
+ return NULL;
}
-NSVGpath* nsvgDuplicatePath(NSVGpath* p)
-{
- NSVGpath* res = NULL;
+NSVGpath *nsvgDuplicatePath(NSVGpath *p) {
+ NSVGpath *res = NULL;
- if (p == NULL)
- return NULL;
+ if (p == NULL)
+ return NULL;
- res = (NSVGpath*)malloc(sizeof(NSVGpath));
- if (res == NULL) goto error;
- memset(res, 0, sizeof(NSVGpath));
+ res = (NSVGpath *)malloc(sizeof(NSVGpath));
+ if (res == NULL)
+ goto error;
+ memset(res, 0, sizeof(NSVGpath));
- res->pts = (float*)malloc(p->npts*2*sizeof(float));
- if (res->pts == NULL) goto error;
- memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2);
- res->npts = p->npts;
+ res->pts = (float *)malloc(p->npts * 2 * sizeof(float));
+ if (res->pts == NULL)
+ goto error;
+ memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2);
+ res->npts = p->npts;
- memcpy(res->bounds, p->bounds, sizeof(p->bounds));
+ memcpy(res->bounds, p->bounds, sizeof(p->bounds));
- res->closed = p->closed;
+ res->closed = p->closed;
- return res;
+ return res;
error:
- if (res != NULL) {
- free(res->pts);
- free(res);
- }
- return NULL;
-}
-
-void nsvgDelete(NSVGimage* image)
-{
- NSVGshape *snext, *shape;
- if (image == NULL) return;
- shape = image->shapes;
- while (shape != NULL) {
- snext = shape->next;
- nsvg__deletePaths(shape->paths);
- nsvg__deletePaint(&shape->fill);
- nsvg__deletePaint(&shape->stroke);
- free(shape);
- shape = snext;
- }
- free(image);
+ if (res != NULL) {
+ free(res->pts);
+ free(res);
+ }
+ return NULL;
+}
+
+void nsvgDelete(NSVGimage *image) {
+ NSVGshape *snext, *shape;
+ if (image == NULL)
+ return;
+ shape = image->shapes;
+ while (shape != NULL) {
+ snext = shape->next;
+ nsvg__deletePaths(shape->paths);
+ nsvg__deletePaint(&shape->fill);
+ nsvg__deletePaint(&shape->stroke);
+ free(shape);
+ shape = snext;
+ }
+ free(image);
}
#endif
#include "vkvg_device_internal.h"
#include "vkvg_context_internal.h"
-#define NANOSVG_IMPLEMENTATION // Expands implementation
+#define NANOSVG_IMPLEMENTATION // Expands implementation
#include "nanosvg.h"
#include "vkvg-svg.h"
-void _svg_set_color (VkvgContext ctx, uint32_t c, float alpha) {
- float a = (c >> 24 & 255) / 255.f;
- float b = (c >> 16 & 255) / 255.f;
- float g = (c >> 8 & 255) / 255.f;
- float r = (c & 255) / 255.f;
- vkvg_set_source_rgba(ctx,r,g,b,a*alpha);
+void _svg_set_color(VkvgContext ctx, uint32_t c, float alpha) {
+ float a = (c >> 24 & 255) / 255.f;
+ float b = (c >> 16 & 255) / 255.f;
+ float g = (c >> 8 & 255) / 255.f;
+ float r = (c & 255) / 255.f;
+ vkvg_set_source_rgba(ctx, r, g, b, a * alpha);
}
-VkvgSurface _svg_load (VkvgDevice dev, NSVGimage* svg) {
- if (svg == NULL) {
- LOG(VKVG_LOG_ERR, "nsvg error");
- return NULL;
- }
- VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT);
- if (!surf)
- return NULL;
+VkvgSurface _svg_load(VkvgDevice dev, NSVGimage *svg) {
+ if (svg == NULL) {
+ LOG(VKVG_LOG_ERR, "nsvg error");
+ return NULL;
+ }
+ VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT);
+ if (!surf)
+ return NULL;
- surf->width = (uint32_t)svg->width;
- surf->height = (uint32_t)svg->height;
- surf->newSurf = true;
+ surf->width = (uint32_t)svg->width;
+ surf->height = (uint32_t)svg->height;
+ surf->newSurf = true;
- _create_surface_images (surf);
+ _create_surface_images(surf);
- VkvgContext ctx = vkvg_create(surf);
- vkvg_svg_render(svg, ctx, NULL);
- vkvg_destroy(ctx);
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_svg_render(svg, ctx, NULL);
+ vkvg_destroy(ctx);
- nsvgDelete(svg);
+ nsvgDelete(svg);
- surf->references = 1;
- vkvg_device_reference (surf->dev);
+ surf->references = 1;
+ vkvg_device_reference(surf->dev);
- return surf;
+ return surf;
}
-VkvgSurface vkvg_surface_create_from_svg (VkvgDevice dev, uint32_t width, uint32_t height, const char* filePath) {
- return _svg_load(dev, nsvgParseFromFile(filePath, "px", (float)dev->hdpi));
+VkvgSurface vkvg_surface_create_from_svg(VkvgDevice dev, uint32_t width, uint32_t height, const char *filePath) {
+ return _svg_load(dev, nsvgParseFromFile(filePath, "px", (float)dev->hdpi));
}
-VkvgSurface vkvg_surface_create_from_svg_fragment (VkvgDevice dev, uint32_t width, uint32_t height, char* svgFragment) {
- return _svg_load(dev, nsvgParse(svgFragment, "px", (float)dev->hdpi));
+VkvgSurface vkvg_surface_create_from_svg_fragment(VkvgDevice dev, uint32_t width, uint32_t height, char *svgFragment) {
+ return _svg_load(dev, nsvgParse(svgFragment, "px", (float)dev->hdpi));
}
-VkvgSvg vkvg_svg_load (const char* svgFilePath) {
- return nsvgParseFromFile(svgFilePath, "px", 96.0f);
-}
-VkvgSvg vkvg_svg_load_fragment (char* svgFragment) {
- return nsvgParse (svgFragment, "px", 96.0f);
-}
-void vkvg_svg_destroy (VkvgSvg svg) {
- nsvgDelete(svg);
-}
-void vkvg_svg_get_dimensions (VkvgSvg svg, uint32_t* width, uint32_t* height) {
- *width = (uint32_t)svg->width;
- *height = (uint32_t)svg->height;
+VkvgSvg vkvg_svg_load(const char *svgFilePath) { return nsvgParseFromFile(svgFilePath, "px", 96.0f); }
+VkvgSvg vkvg_svg_load_fragment(char *svgFragment) { return nsvgParse(svgFragment, "px", 96.0f); }
+void vkvg_svg_destroy(VkvgSvg svg) { nsvgDelete(svg); }
+void vkvg_svg_get_dimensions(VkvgSvg svg, uint32_t *width, uint32_t *height) {
+ *width = (uint32_t)svg->width;
+ *height = (uint32_t)svg->height;
}
-void vkvg_svg_render (VkvgSvg svg, VkvgContext ctx, const char* subId){
- NSVGshape* shape;
- NSVGpath* path;
- vkvg_save (ctx);
-
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
-
- vkvg_set_source_rgba(ctx,0.0,0.0,0.0,1);
-
- for (shape = svg->shapes; shape != NULL; shape = shape->next) {
- if (subId != NULL) {
- if (strcmp(shape->id, subId)!=0)
- continue;
- }
-
- vkvg_new_path(ctx);
-
- float o = shape->opacity;
-
- vkvg_set_line_width(ctx, shape->strokeWidth);
-
- for (path = shape->paths; path != NULL; path = path->next) {
- float* p = path->pts;
- vkvg_move_to(ctx, p[0],p[1]);
- for (int i = 1; i < path->npts; i += 3) {
- p = &path->pts[i*2];
- vkvg_curve_to(ctx, p[0],p[1], p[2],p[3], p[4],p[5]);
- }
- if (path->closed)
- vkvg_close_path(ctx);
- }
-
- if (shape->fill.type == NSVG_PAINT_COLOR)
- _svg_set_color(ctx, shape->fill.color, o);
- else if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT){
- NSVGgradient* g = shape->fill.gradient;
- _svg_set_color(ctx, g->stops[0].color, o);
- }
-
- if (shape->fill.type != NSVG_PAINT_NONE){
- if (shape->stroke.type == NSVG_PAINT_NONE){
- vkvg_fill(ctx);
- continue;
- }
- vkvg_fill_preserve (ctx);
- }
-
- if (shape->stroke.type == NSVG_PAINT_COLOR)
- _svg_set_color(ctx, shape->stroke.color, o);
- else if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT){
- NSVGgradient* g = shape->stroke.gradient;
- _svg_set_color(ctx, g->stops[0].color, o);
- }
-
- vkvg_stroke(ctx);
- }
- vkvg_restore (ctx);
+void vkvg_svg_render(VkvgSvg svg, VkvgContext ctx, const char *subId) {
+ NSVGshape *shape;
+ NSVGpath *path;
+ vkvg_save(ctx);
+
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+
+ vkvg_set_source_rgba(ctx, 0.0, 0.0, 0.0, 1);
+
+ for (shape = svg->shapes; shape != NULL; shape = shape->next) {
+ if (subId != NULL) {
+ if (strcmp(shape->id, subId) != 0)
+ continue;
+ }
+
+ vkvg_new_path(ctx);
+
+ float o = shape->opacity;
+
+ vkvg_set_line_width(ctx, shape->strokeWidth);
+
+ for (path = shape->paths; path != NULL; path = path->next) {
+ float *p = path->pts;
+ vkvg_move_to(ctx, p[0], p[1]);
+ for (int i = 1; i < path->npts; i += 3) {
+ p = &path->pts[i * 2];
+ vkvg_curve_to(ctx, p[0], p[1], p[2], p[3], p[4], p[5]);
+ }
+ if (path->closed)
+ vkvg_close_path(ctx);
+ }
+
+ if (shape->fill.type == NSVG_PAINT_COLOR)
+ _svg_set_color(ctx, shape->fill.color, o);
+ else if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT) {
+ NSVGgradient *g = shape->fill.gradient;
+ _svg_set_color(ctx, g->stops[0].color, o);
+ }
+
+ if (shape->fill.type != NSVG_PAINT_NONE) {
+ if (shape->stroke.type == NSVG_PAINT_NONE) {
+ vkvg_fill(ctx);
+ continue;
+ }
+ vkvg_fill_preserve(ctx);
+ }
+
+ if (shape->stroke.type == NSVG_PAINT_COLOR)
+ _svg_set_color(ctx, shape->stroke.color, o);
+ else if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT) {
+ NSVGgradient *g = shape->stroke.gradient;
+ _svg_set_color(ctx, g->stops[0].color, o);
+ }
+
+ vkvg_stroke(ctx);
+ }
+ vkvg_restore(ctx);
}
#include "vkvg_record_internal.h"
#ifdef VKVG_RECORDING
-void vkvg_start_recording (VkvgContext ctx) {
- if (ctx->status)
- return;
- _start_recording(ctx);
+void vkvg_start_recording(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+ _start_recording(ctx);
}
-VkvgRecording vkvg_stop_recording (VkvgContext ctx) {
- if (ctx->status)
- return NULL;
- return _stop_recording (ctx);
+VkvgRecording vkvg_stop_recording(VkvgContext ctx) {
+ if (ctx->status)
+ return NULL;
+ return _stop_recording(ctx);
}
-uint32_t vkvg_recording_get_count (VkvgRecording rec) {
- if (!rec)
- return 0;
- return rec->commandsCount;
+uint32_t vkvg_recording_get_count(VkvgRecording rec) {
+ if (!rec)
+ return 0;
+ return rec->commandsCount;
}
-void* vkvg_recording_get_data (VkvgRecording rec) {
- if (!rec)
- return 0;
- return rec->buffer;
+void *vkvg_recording_get_data(VkvgRecording rec) {
+ if (!rec)
+ return 0;
+ return rec->buffer;
}
-void vkvg_recording_get_command (VkvgRecording rec, uint32_t cmdIndex, uint32_t* cmd, void** dataOffset) {
- if (!rec)
- return;
- if (cmdIndex < rec->commandsCount) {
- *cmd = rec->commands[cmdIndex].cmd;
- *dataOffset = (void*)rec->commands[cmdIndex].dataOffset;
- } else {
- *cmd = 0;
- *dataOffset = NULL;
- }
-
+void vkvg_recording_get_command(VkvgRecording rec, uint32_t cmdIndex, uint32_t *cmd, void **dataOffset) {
+ if (!rec)
+ return;
+ if (cmdIndex < rec->commandsCount) {
+ *cmd = rec->commands[cmdIndex].cmd;
+ *dataOffset = (void *)rec->commands[cmdIndex].dataOffset;
+ } else {
+ *cmd = 0;
+ *dataOffset = NULL;
+ }
}
-void vkvg_replay (VkvgContext ctx, VkvgRecording rec) {
- if (!rec)
- return;
- for (uint32_t i=0; i<rec->commandsCount; i++)
- _replay_command(ctx, rec, i);
+void vkvg_replay(VkvgContext ctx, VkvgRecording rec) {
+ if (!rec)
+ return;
+ for (uint32_t i = 0; i < rec->commandsCount; i++)
+ _replay_command(ctx, rec, i);
}
-void vkvg_replay_command (VkvgContext ctx, VkvgRecording rec, uint32_t cmdIndex) {
- if (!rec)
- return;
- if (cmdIndex < rec->commandsCount)
- _replay_command(ctx, rec, cmdIndex);
+void vkvg_replay_command(VkvgContext ctx, VkvgRecording rec, uint32_t cmdIndex) {
+ if (!rec)
+ return;
+ if (cmdIndex < rec->commandsCount)
+ _replay_command(ctx, rec, cmdIndex);
}
-void vkvg_recording_destroy (VkvgRecording rec) {
- if (!rec)
- return;
- _destroy_recording(rec);
+void vkvg_recording_destroy(VkvgRecording rec) {
+ if (!rec)
+ return;
+ _destroy_recording(rec);
}
#endif
#include "vkvg_record_internal.h"
#include "vkvg_context_internal.h"
-#define VKVG_RECORDING_INIT_BUFFER_SIZE_TRESHOLD 64
-#define VKVG_RECORDING_INIT_BUFFER_SIZE 1024
-#define VKVG_RECORDING_INIT_COMMANDS_COUNT 64
+#define VKVG_RECORDING_INIT_BUFFER_SIZE_TRESHOLD 64
+#define VKVG_RECORDING_INIT_BUFFER_SIZE 1024
+#define VKVG_RECORDING_INIT_COMMANDS_COUNT 64
-vkvg_recording_t* _new_recording () {
+vkvg_recording_t *_new_recording() {
- vkvg_recording_t* rec = (vkvg_recording_t*)calloc(1,sizeof (vkvg_recording_t));
+ vkvg_recording_t *rec = (vkvg_recording_t *)calloc(1, sizeof(vkvg_recording_t));
- rec->commandsReservedCount = VKVG_RECORDING_INIT_COMMANDS_COUNT;
- rec->bufferReservedSize = VKVG_RECORDING_INIT_BUFFER_SIZE;
- rec->commands = (vkvg_record_t*)malloc(rec->commandsReservedCount * sizeof (vkvg_record_t));
- rec->buffer = malloc (rec->bufferReservedSize);
+ rec->commandsReservedCount = VKVG_RECORDING_INIT_COMMANDS_COUNT;
+ rec->bufferReservedSize = VKVG_RECORDING_INIT_BUFFER_SIZE;
+ rec->commands = (vkvg_record_t *)malloc(rec->commandsReservedCount * sizeof(vkvg_record_t));
+ rec->buffer = malloc(rec->bufferReservedSize);
- return rec;
+ return rec;
}
-void _destroy_recording (vkvg_recording_t* rec) {
- if (!rec)
- return;
- for (uint32_t i=0; i<rec->commandsCount; i++) {
- if (rec->commands[i].cmd == VKVG_CMD_SET_SOURCE)
- vkvg_pattern_destroy((VkvgPattern)(rec->buffer + rec->commands[i].dataOffset));
- else if (rec->commands[i].cmd == VKVG_CMD_SET_SOURCE_SURFACE)
- vkvg_surface_destroy ((VkvgSurface)(rec->buffer + rec->commands[i].dataOffset + 2 * sizeof(float)));
- }
- free(rec->commands);
- free(rec->buffer);
- free(rec);
+void _destroy_recording(vkvg_recording_t *rec) {
+ if (!rec)
+ return;
+ for (uint32_t i = 0; i < rec->commandsCount; i++) {
+ if (rec->commands[i].cmd == VKVG_CMD_SET_SOURCE)
+ vkvg_pattern_destroy((VkvgPattern)(rec->buffer + rec->commands[i].dataOffset));
+ else if (rec->commands[i].cmd == VKVG_CMD_SET_SOURCE_SURFACE)
+ vkvg_surface_destroy((VkvgSurface)(rec->buffer + rec->commands[i].dataOffset + 2 * sizeof(float)));
+ }
+ free(rec->commands);
+ free(rec->buffer);
+ free(rec);
}
-void _start_recording (VkvgContext ctx) {
- if (ctx->recording)
- _destroy_recording(ctx->recording);
- ctx->recording = _new_recording();
+void _start_recording(VkvgContext ctx) {
+ if (ctx->recording)
+ _destroy_recording(ctx->recording);
+ ctx->recording = _new_recording();
}
-vkvg_recording_t* _stop_recording (VkvgContext ctx) {
- vkvg_recording_t* rec = ctx->recording;
- if (!rec)
- return NULL;
- if (!rec->commandsCount) {
- _destroy_recording(rec);
- ctx->recording = NULL;
- return NULL;
- }
- /*rec->buffer = realloc(rec->buffer, rec->bufferSize);
- rec->commands = (vkvg_record_t*)realloc(rec->commands, rec->commandsCount * sizeof (vkvg_record_t));*/
- ctx->recording = NULL;
- return rec;
+vkvg_recording_t *_stop_recording(VkvgContext ctx) {
+ vkvg_recording_t *rec = ctx->recording;
+ if (!rec)
+ return NULL;
+ if (!rec->commandsCount) {
+ _destroy_recording(rec);
+ ctx->recording = NULL;
+ return NULL;
+ }
+ /*rec->buffer = realloc(rec->buffer, rec->bufferSize);
+ rec->commands = (vkvg_record_t*)realloc(rec->commands, rec->commandsCount * sizeof (vkvg_record_t));*/
+ ctx->recording = NULL;
+ return rec;
}
-void* _ensure_recording_buffer (vkvg_recording_t* rec, size_t size) {
- if (rec->bufferReservedSize >= rec->bufferSize - VKVG_RECORDING_INIT_BUFFER_SIZE_TRESHOLD - size) {
- rec->bufferReservedSize += VKVG_RECORDING_INIT_BUFFER_SIZE;
- rec->buffer = realloc(rec->buffer, rec->bufferReservedSize);
- }
- return rec->buffer + rec->bufferSize;
+void *_ensure_recording_buffer(vkvg_recording_t *rec, size_t size) {
+ if (rec->bufferReservedSize >= rec->bufferSize - VKVG_RECORDING_INIT_BUFFER_SIZE_TRESHOLD - size) {
+ rec->bufferReservedSize += VKVG_RECORDING_INIT_BUFFER_SIZE;
+ rec->buffer = realloc(rec->buffer, rec->bufferReservedSize);
+ }
+ return rec->buffer + rec->bufferSize;
}
-void* _advance_recording_buffer_unchecked (vkvg_recording_t* rec, size_t size) {
- rec->bufferSize += size;
- return rec->buffer + rec->bufferSize;
+void *_advance_recording_buffer_unchecked(vkvg_recording_t *rec, size_t size) {
+ rec->bufferSize += size;
+ return rec->buffer + rec->bufferSize;
}
-#define STORE_FLOATS(floatcount) \
- for (i=0; i<floatcount; i++) { \
- buff = _ensure_recording_buffer (rec, sizeof(float)); \
- *(float*)buff = (float)va_arg(args, double); \
- buff = _advance_recording_buffer_unchecked (rec, sizeof(float));\
- }
-#define STORE_BOOLS(count) \
- for (i=0; i<count; i++) { \
- buff = _ensure_recording_buffer (rec, sizeof(bool)); \
- *(bool*)buff = (bool)va_arg(args, int); \
- _advance_recording_buffer_unchecked (rec, sizeof(bool)); \
- }
-#define STORE_UINT32(count) \
- for (i=0; i<count; i++) { \
- buff = _ensure_recording_buffer (rec, sizeof(uint32_t)); \
- *(uint32_t*)buff = (uint32_t)va_arg(args, uint32_t); \
- buff = _advance_recording_buffer_unchecked (rec, sizeof(uint32_t)); \
- }
+#define STORE_FLOATS(floatcount) \
+ for (i = 0; i < floatcount; i++) { \
+ buff = _ensure_recording_buffer(rec, sizeof(float)); \
+ *(float *)buff = (float)va_arg(args, double); \
+ buff = _advance_recording_buffer_unchecked(rec, sizeof(float)); \
+ }
+#define STORE_BOOLS(count) \
+ for (i = 0; i < count; i++) { \
+ buff = _ensure_recording_buffer(rec, sizeof(bool)); \
+ *(bool *)buff = (bool)va_arg(args, int); \
+ _advance_recording_buffer_unchecked(rec, sizeof(bool)); \
+ }
+#define STORE_UINT32(count) \
+ for (i = 0; i < count; i++) { \
+ buff = _ensure_recording_buffer(rec, sizeof(uint32_t)); \
+ *(uint32_t *)buff = (uint32_t)va_arg(args, uint32_t); \
+ buff = _advance_recording_buffer_unchecked(rec, sizeof(uint32_t)); \
+ }
-void _record (vkvg_recording_t* rec,...) {
- va_list args;
- va_start(args, rec);
+void _record(vkvg_recording_t *rec, ...) {
+ va_list args;
+ va_start(args, rec);
- uint32_t cmd = va_arg(args, uint32_t);
+ uint32_t cmd = va_arg(args, uint32_t);
- if (rec->commandsCount == rec->commandsReservedCount) {
- rec->commandsReservedCount += VKVG_RECORDING_INIT_COMMANDS_COUNT;
- rec->commands = (vkvg_record_t*)realloc(rec->commands, rec->commandsReservedCount * sizeof (vkvg_record_t));
- }
- vkvg_record_t* r = &rec->commands[rec->commandsCount++];
- r->cmd = cmd;
- r->dataOffset = rec->bufferSize;
+ if (rec->commandsCount == rec->commandsReservedCount) {
+ rec->commandsReservedCount += VKVG_RECORDING_INIT_COMMANDS_COUNT;
+ rec->commands = (vkvg_record_t *)realloc(rec->commands, rec->commandsReservedCount * sizeof(vkvg_record_t));
+ }
+ vkvg_record_t *r = &rec->commands[rec->commandsCount++];
+ r->cmd = cmd;
+ r->dataOffset = rec->bufferSize;
- char* buff;
- int i = 0;
+ char *buff;
+ int i = 0;
- if (cmd & VKVG_CMD_PATH_COMMANDS) {
- if ((cmd & VKVG_CMD_PATHPROPS_COMMANDS) == VKVG_CMD_PATHPROPS_COMMANDS) {
- switch (r->cmd) {
- case VKVG_CMD_SET_LINE_WIDTH:
- case VKVG_CMD_SET_MITER_LIMIT:
- STORE_FLOATS(1);
- break;
- case VKVG_CMD_SET_LINE_JOIN:
- STORE_UINT32(1);
- break;
- case VKVG_CMD_SET_LINE_CAP:
- STORE_UINT32(1);
- break;
- case VKVG_CMD_SET_OPERATOR:
- STORE_UINT32(1);
- break;
- case VKVG_CMD_SET_FILL_RULE:
- STORE_UINT32(1);
- break;
- case VKVG_CMD_SET_DASH:
- break;
- }
- } else {
- switch (cmd) {
- case VKVG_CMD_MOVE_TO:
- case VKVG_CMD_LINE_TO:
- case VKVG_CMD_REL_MOVE_TO:
- case VKVG_CMD_REL_LINE_TO:
- STORE_FLOATS(2);
- break;
- case VKVG_CMD_RECTANGLE:
- case VKVG_CMD_QUADRATIC_TO:
- case VKVG_CMD_REL_QUADRATIC_TO:
- STORE_FLOATS(4);
- break;
- case VKVG_CMD_ARC:
- case VKVG_CMD_ARC_NEG:
- STORE_FLOATS(5);
- break;
- case VKVG_CMD_CURVE_TO:
- case VKVG_CMD_REL_CURVE_TO:
- STORE_FLOATS(6);
- break;
- case VKVG_CMD_ELLIPTICAL_ARC_TO:
- case VKVG_CMD_REL_ELLIPTICAL_ARC_TO:
- STORE_FLOATS(5);
- STORE_BOOLS(2);
- break;
- case VKVG_CMD_NEW_PATH:
- case VKVG_CMD_NEW_SUB_PATH:
- case VKVG_CMD_CLOSE_PATH:
- break;
- }
- }
- } else if (!(r->cmd & VKVG_CMD_DRAW_COMMANDS)) {
- if (r->cmd & VKVG_CMD_TRANSFORM_COMMANDS) {
- switch (r->cmd) {
- case VKVG_CMD_TRANSLATE:
- case VKVG_CMD_SCALE:
- STORE_FLOATS(2);
- break;
- case VKVG_CMD_ROTATE:
- STORE_FLOATS(1);
- break;
- case VKVG_CMD_IDENTITY_MATRIX:
- break;
- case VKVG_CMD_SET_MATRIX:
- case VKVG_CMD_TRANSFORM:
- {
- buff = _ensure_recording_buffer (rec, sizeof(vkvg_matrix_t));
- vkvg_matrix_t* mat = (vkvg_matrix_t*)va_arg(args, vkvg_matrix_t*);
- memcpy(buff, mat, sizeof(vkvg_matrix_t));
- buff = _advance_recording_buffer_unchecked (rec, sizeof(vkvg_matrix_t));
+ if (cmd & VKVG_CMD_PATH_COMMANDS) {
+ if ((cmd & VKVG_CMD_PATHPROPS_COMMANDS) == VKVG_CMD_PATHPROPS_COMMANDS) {
+ switch (r->cmd) {
+ case VKVG_CMD_SET_LINE_WIDTH:
+ case VKVG_CMD_SET_MITER_LIMIT:
+ STORE_FLOATS(1);
+ break;
+ case VKVG_CMD_SET_LINE_JOIN:
+ STORE_UINT32(1);
+ break;
+ case VKVG_CMD_SET_LINE_CAP:
+ STORE_UINT32(1);
+ break;
+ case VKVG_CMD_SET_OPERATOR:
+ STORE_UINT32(1);
+ break;
+ case VKVG_CMD_SET_FILL_RULE:
+ STORE_UINT32(1);
+ break;
+ case VKVG_CMD_SET_DASH:
+ break;
+ }
+ } else {
+ switch (cmd) {
+ case VKVG_CMD_MOVE_TO:
+ case VKVG_CMD_LINE_TO:
+ case VKVG_CMD_REL_MOVE_TO:
+ case VKVG_CMD_REL_LINE_TO:
+ STORE_FLOATS(2);
+ break;
+ case VKVG_CMD_RECTANGLE:
+ case VKVG_CMD_QUADRATIC_TO:
+ case VKVG_CMD_REL_QUADRATIC_TO:
+ STORE_FLOATS(4);
+ break;
+ case VKVG_CMD_ARC:
+ case VKVG_CMD_ARC_NEG:
+ STORE_FLOATS(5);
+ break;
+ case VKVG_CMD_CURVE_TO:
+ case VKVG_CMD_REL_CURVE_TO:
+ STORE_FLOATS(6);
+ break;
+ case VKVG_CMD_ELLIPTICAL_ARC_TO:
+ case VKVG_CMD_REL_ELLIPTICAL_ARC_TO:
+ STORE_FLOATS(5);
+ STORE_BOOLS(2);
+ break;
+ case VKVG_CMD_NEW_PATH:
+ case VKVG_CMD_NEW_SUB_PATH:
+ case VKVG_CMD_CLOSE_PATH:
+ break;
+ }
+ }
+ } else if (!(r->cmd & VKVG_CMD_DRAW_COMMANDS)) {
+ if (r->cmd & VKVG_CMD_TRANSFORM_COMMANDS) {
+ switch (r->cmd) {
+ case VKVG_CMD_TRANSLATE:
+ case VKVG_CMD_SCALE:
+ STORE_FLOATS(2);
+ break;
+ case VKVG_CMD_ROTATE:
+ STORE_FLOATS(1);
+ break;
+ case VKVG_CMD_IDENTITY_MATRIX:
+ break;
+ case VKVG_CMD_SET_MATRIX:
+ case VKVG_CMD_TRANSFORM: {
+ buff = _ensure_recording_buffer(rec, sizeof(vkvg_matrix_t));
+ vkvg_matrix_t *mat = (vkvg_matrix_t *)va_arg(args, vkvg_matrix_t *);
+ memcpy(buff, mat, sizeof(vkvg_matrix_t));
+ buff = _advance_recording_buffer_unchecked(rec, sizeof(vkvg_matrix_t));
- }
- break;
- }
- } else if (r->cmd & VKVG_CMD_PATTERN_COMMANDS) {
- switch (r->cmd) {
- case VKVG_CMD_SET_SOURCE_RGBA:
- STORE_FLOATS(4);
- break;
- case VKVG_CMD_SET_SOURCE_RGB:
- STORE_FLOATS(3);
- break;
- case VKVG_CMD_SET_SOURCE_COLOR:
- STORE_UINT32(1);
- break;
- case VKVG_CMD_SET_SOURCE:
- {
- buff = _ensure_recording_buffer (rec, sizeof(VkvgPattern));
- VkvgPattern pat = (VkvgPattern)va_arg(args, VkvgPattern);
- vkvg_pattern_reference(pat);
- VkvgPattern* pPat = (VkvgPattern*)buff;
- *pPat = pat;
- _advance_recording_buffer_unchecked (rec, sizeof(VkvgPattern));
- }
- break;
- case VKVG_CMD_SET_SOURCE_SURFACE:
- STORE_FLOATS(2);
- {
- buff = _ensure_recording_buffer (rec, sizeof(VkvgSurface));
- VkvgSurface surf = (VkvgSurface)va_arg(args, VkvgSurface);
- vkvg_surface_reference(surf);
- *(VkvgSurface*)buff = surf;
- _advance_recording_buffer_unchecked (rec, sizeof(VkvgSurface));
- }
- break;
- }
- } else if (r->cmd & VKVG_CMD_TEXT_COMMANDS) {
- char* txt;
- int txtLen;
- switch (r->cmd) {
- case VKVG_CMD_SET_FONT_SIZE:
- STORE_UINT32(1);
- break;
- case VKVG_CMD_SHOW_TEXT:
- case VKVG_CMD_SET_FONT_FACE:
- txt = (char*)va_arg(args, char*);
- txtLen = strlen(txt);
- buff = _ensure_recording_buffer (rec, txtLen * sizeof(char));
- strcpy(buff, txt);
- _advance_recording_buffer_unchecked (rec, txtLen * sizeof(char));
- break;
- case VKVG_CMD_SET_FONT_PATH:
- break;
- }
- }
- }
- va_end(args);
+ } break;
+ }
+ } else if (r->cmd & VKVG_CMD_PATTERN_COMMANDS) {
+ switch (r->cmd) {
+ case VKVG_CMD_SET_SOURCE_RGBA:
+ STORE_FLOATS(4);
+ break;
+ case VKVG_CMD_SET_SOURCE_RGB:
+ STORE_FLOATS(3);
+ break;
+ case VKVG_CMD_SET_SOURCE_COLOR:
+ STORE_UINT32(1);
+ break;
+ case VKVG_CMD_SET_SOURCE: {
+ buff = _ensure_recording_buffer(rec, sizeof(VkvgPattern));
+ VkvgPattern pat = (VkvgPattern)va_arg(args, VkvgPattern);
+ vkvg_pattern_reference(pat);
+ VkvgPattern *pPat = (VkvgPattern *)buff;
+ *pPat = pat;
+ _advance_recording_buffer_unchecked(rec, sizeof(VkvgPattern));
+ } break;
+ case VKVG_CMD_SET_SOURCE_SURFACE:
+ STORE_FLOATS(2);
+ {
+ buff = _ensure_recording_buffer(rec, sizeof(VkvgSurface));
+ VkvgSurface surf = (VkvgSurface)va_arg(args, VkvgSurface);
+ vkvg_surface_reference(surf);
+ *(VkvgSurface *)buff = surf;
+ _advance_recording_buffer_unchecked(rec, sizeof(VkvgSurface));
+ }
+ break;
+ }
+ } else if (r->cmd & VKVG_CMD_TEXT_COMMANDS) {
+ char *txt;
+ int txtLen;
+ switch (r->cmd) {
+ case VKVG_CMD_SET_FONT_SIZE:
+ STORE_UINT32(1);
+ break;
+ case VKVG_CMD_SHOW_TEXT:
+ case VKVG_CMD_SET_FONT_FACE:
+ txt = (char *)va_arg(args, char *);
+ txtLen = strlen(txt);
+ buff = _ensure_recording_buffer(rec, txtLen * sizeof(char));
+ strcpy(buff, txt);
+ _advance_recording_buffer_unchecked(rec, txtLen * sizeof(char));
+ break;
+ case VKVG_CMD_SET_FONT_PATH:
+ break;
+ }
+ }
+ }
+ va_end(args);
}
-void _replay_command (VkvgContext ctx, VkvgRecording rec, uint32_t index) {
- vkvg_record_t* r = &rec->commands[index];
- float* floats = (float*)(rec->buffer + r->dataOffset);
- uint32_t* uints = (uint32_t*)floats;
- if (r->cmd&VKVG_CMD_PATH_COMMANDS) {
- if ((r->cmd&VKVG_CMD_RELATIVE_COMMANDS)==VKVG_CMD_RELATIVE_COMMANDS) {
- switch (r->cmd) {
- case VKVG_CMD_REL_MOVE_TO:
- vkvg_rel_move_to(ctx, floats[0], floats[1]);
- return;
- case VKVG_CMD_REL_LINE_TO:
- vkvg_rel_line_to(ctx, floats[0], floats[1]);
- return;
- case VKVG_CMD_REL_CURVE_TO:
- vkvg_rel_curve_to (ctx, floats[0], floats[1], floats[2], floats[3], floats[4], floats[5]);
- return;
- case VKVG_CMD_REL_QUADRATIC_TO:
- vkvg_rel_quadratic_to (ctx, floats[0], floats[1], floats[2], floats[3]);
- return;
- case VKVG_CMD_REL_ELLIPTICAL_ARC_TO:
- {
- bool* flags = (bool*)&floats[5];
- vkvg_rel_elliptic_arc_to (ctx, floats[0], floats[1], flags[0], flags[1], floats[2], floats[3], floats[4]);
- }
- return;
- }
- }else if ((r->cmd&VKVG_CMD_PATHPROPS_COMMANDS)==VKVG_CMD_PATHPROPS_COMMANDS) {
- switch (r->cmd) {
- case VKVG_CMD_SET_LINE_WIDTH:
- vkvg_set_line_width (ctx, floats[0]);
- return;
- case VKVG_CMD_SET_MITER_LIMIT:
- vkvg_set_miter_limit (ctx, floats[0]);
- return;
- case VKVG_CMD_SET_LINE_JOIN:
- vkvg_set_line_join (ctx, (vkvg_line_join_t)uints[0]);
- return;
- case VKVG_CMD_SET_LINE_CAP:
- vkvg_set_line_cap (ctx, (vkvg_line_cap_t)uints[0]);
- return;
- case VKVG_CMD_SET_OPERATOR:
- vkvg_set_operator (ctx, (vkvg_operator_t)uints[0]);
- return;
- case VKVG_CMD_SET_FILL_RULE:
- vkvg_set_fill_rule (ctx, (vkvg_fill_rule_t)uints[0]);
- return;
- case VKVG_CMD_SET_DASH:
- vkvg_set_dash(ctx, &floats[2], uints[0], floats[1]);
- return;
- }
- } else {
- switch (r->cmd) {
- case VKVG_CMD_NEW_PATH:
- vkvg_new_path (ctx);
- return;
- case VKVG_CMD_NEW_SUB_PATH:
- vkvg_new_sub_path (ctx);
- return;
- case VKVG_CMD_CLOSE_PATH:
- vkvg_close_path (ctx);
- return;
- case VKVG_CMD_RECTANGLE:
- vkvg_rectangle (ctx, floats[0], floats[1], floats[2], floats[3]);
- return;
- case VKVG_CMD_ARC:
- vkvg_arc (ctx, floats[0], floats[1], floats[2], floats[3], floats[4]);
- return;
- case VKVG_CMD_ARC_NEG:
- vkvg_arc (ctx, floats[0], floats[1], floats[2], floats[3], floats[4]);
- return;
- /*case VKVG_CMD_ELLIPSE:
- vkvg_ellipse (ctx, floats[0], floats[1], floats[2], floats[3], floats[4]);
- break;*/
- case VKVG_CMD_MOVE_TO:
- vkvg_move_to(ctx, floats[0], floats[1]);
- return;
- case VKVG_CMD_LINE_TO:
- vkvg_line_to(ctx, floats[0], floats[1]);
- return;
- case VKVG_CMD_CURVE_TO:
- vkvg_curve_to (ctx, floats[0], floats[1], floats[2], floats[3], floats[4], floats[5]);
- return;
- case VKVG_CMD_ELLIPTICAL_ARC_TO:
- {
- bool* flags = (bool*)&floats[5];
- vkvg_elliptic_arc_to (ctx, floats[0], floats[1], flags[0], flags[1], floats[2], floats[3], floats[4]);
- }
- return;
- case VKVG_CMD_QUADRATIC_TO:
- vkvg_quadratic_to (ctx, floats[0], floats[1], floats[2], floats[3]);
- return;
- }
- }
- } else if (r->cmd & VKVG_CMD_DRAW_COMMANDS) {
- switch (r->cmd) {
- case VKVG_CMD_PAINT:
- vkvg_paint (ctx);
- return;
- case VKVG_CMD_FILL:
- vkvg_fill (ctx);
- return;
- case VKVG_CMD_STROKE:
- vkvg_stroke (ctx);
- return;
- case VKVG_CMD_CLIP:
- vkvg_clip (ctx);
- return;
- case VKVG_CMD_CLEAR:
- vkvg_clear (ctx);
- return;
- case VKVG_CMD_FILL_PRESERVE:
- vkvg_fill_preserve (ctx);
- return;
- case VKVG_CMD_STROKE_PRESERVE:
- vkvg_stroke_preserve (ctx);
- return;
- case VKVG_CMD_CLIP_PRESERVE:
- vkvg_clip_preserve (ctx);
- return;
- }
- } else if (r->cmd & VKVG_CMD_TRANSFORM_COMMANDS) {
- switch (r->cmd) {
- case VKVG_CMD_TRANSLATE:
- vkvg_translate (ctx, floats[0], floats[1]);
- return;
- case VKVG_CMD_SCALE:
- vkvg_scale (ctx, floats[0], floats[1]);
- return;
- case VKVG_CMD_ROTATE:
- vkvg_rotate (ctx, floats[0]);
- return;
- case VKVG_CMD_IDENTITY_MATRIX:
- vkvg_identity_matrix (ctx);
- return;
- case VKVG_CMD_TRANSFORM:
- {
- vkvg_matrix_t* mat = (vkvg_matrix_t*)&floats[0];
- vkvg_transform (ctx, mat);
- }
- return;
- case VKVG_CMD_SET_MATRIX:
- {
- vkvg_matrix_t* mat = (vkvg_matrix_t*)&floats[0];
- vkvg_set_matrix (ctx, mat);
- }
- return;
- }
- } else if (r->cmd & VKVG_CMD_PATTERN_COMMANDS) {
- switch (r->cmd) {
- case VKVG_CMD_SET_SOURCE_RGB:
- vkvg_set_source_rgb (ctx, floats[0], floats[1], floats[2]);
- return;
- case VKVG_CMD_SET_SOURCE_RGBA:
- vkvg_set_source_rgba (ctx, floats[0], floats[1], floats[2], floats[3]);
- return;
- case VKVG_CMD_SET_SOURCE_COLOR:
- vkvg_set_source_color (ctx, uints[0]);
- return;
- case VKVG_CMD_SET_SOURCE:
- {
- VkvgPattern pat = *((VkvgPattern*)(rec->buffer + r->dataOffset));
- vkvg_set_source (ctx, pat);
- }
- return;
- case VKVG_CMD_SET_SOURCE_SURFACE:
- {
- VkvgSurface surf = *((VkvgSurface*)&floats[2]);
- vkvg_set_source_surface (ctx, surf, floats[0], floats[1]);
- }
- return;
- }
- } else if (r->cmd & VKVG_CMD_TEXT_COMMANDS) {
- char* txt = (char*)floats;
- switch (r->cmd) {
- case VKVG_CMD_SET_FONT_SIZE:
- vkvg_set_font_size (ctx, uints[0]);
- return;
- case VKVG_CMD_SET_FONT_FACE:
- vkvg_select_font_face (ctx, txt);
- return;
- /*case VKVG_CMD_SET_FONT_PATH:
- vkvg_load_font_from_path (ctx, txt);
- return; */
- case VKVG_CMD_SHOW_TEXT:
- vkvg_show_text (ctx, txt);
- return;
- }
- } else {
- switch (r->cmd) {
- case VKVG_CMD_SAVE:
- vkvg_save (ctx);
- return;
- case VKVG_CMD_RESTORE:
- vkvg_restore (ctx);
- return;
- }
- }
- LOG(VKVG_LOG_ERR, "[REPLAY] unimplemented command: %.4x\n", r->cmd);
+void _replay_command(VkvgContext ctx, VkvgRecording rec, uint32_t index) {
+ vkvg_record_t *r = &rec->commands[index];
+ float *floats = (float *)(rec->buffer + r->dataOffset);
+ uint32_t *uints = (uint32_t *)floats;
+ if (r->cmd & VKVG_CMD_PATH_COMMANDS) {
+ if ((r->cmd & VKVG_CMD_RELATIVE_COMMANDS) == VKVG_CMD_RELATIVE_COMMANDS) {
+ switch (r->cmd) {
+ case VKVG_CMD_REL_MOVE_TO:
+ vkvg_rel_move_to(ctx, floats[0], floats[1]);
+ return;
+ case VKVG_CMD_REL_LINE_TO:
+ vkvg_rel_line_to(ctx, floats[0], floats[1]);
+ return;
+ case VKVG_CMD_REL_CURVE_TO:
+ vkvg_rel_curve_to(ctx, floats[0], floats[1], floats[2], floats[3], floats[4], floats[5]);
+ return;
+ case VKVG_CMD_REL_QUADRATIC_TO:
+ vkvg_rel_quadratic_to(ctx, floats[0], floats[1], floats[2], floats[3]);
+ return;
+ case VKVG_CMD_REL_ELLIPTICAL_ARC_TO: {
+ bool *flags = (bool *)&floats[5];
+ vkvg_rel_elliptic_arc_to(ctx, floats[0], floats[1], flags[0], flags[1], floats[2], floats[3],
+ floats[4]);
+ }
+ return;
+ }
+ } else if ((r->cmd & VKVG_CMD_PATHPROPS_COMMANDS) == VKVG_CMD_PATHPROPS_COMMANDS) {
+ switch (r->cmd) {
+ case VKVG_CMD_SET_LINE_WIDTH:
+ vkvg_set_line_width(ctx, floats[0]);
+ return;
+ case VKVG_CMD_SET_MITER_LIMIT:
+ vkvg_set_miter_limit(ctx, floats[0]);
+ return;
+ case VKVG_CMD_SET_LINE_JOIN:
+ vkvg_set_line_join(ctx, (vkvg_line_join_t)uints[0]);
+ return;
+ case VKVG_CMD_SET_LINE_CAP:
+ vkvg_set_line_cap(ctx, (vkvg_line_cap_t)uints[0]);
+ return;
+ case VKVG_CMD_SET_OPERATOR:
+ vkvg_set_operator(ctx, (vkvg_operator_t)uints[0]);
+ return;
+ case VKVG_CMD_SET_FILL_RULE:
+ vkvg_set_fill_rule(ctx, (vkvg_fill_rule_t)uints[0]);
+ return;
+ case VKVG_CMD_SET_DASH:
+ vkvg_set_dash(ctx, &floats[2], uints[0], floats[1]);
+ return;
+ }
+ } else {
+ switch (r->cmd) {
+ case VKVG_CMD_NEW_PATH:
+ vkvg_new_path(ctx);
+ return;
+ case VKVG_CMD_NEW_SUB_PATH:
+ vkvg_new_sub_path(ctx);
+ return;
+ case VKVG_CMD_CLOSE_PATH:
+ vkvg_close_path(ctx);
+ return;
+ case VKVG_CMD_RECTANGLE:
+ vkvg_rectangle(ctx, floats[0], floats[1], floats[2], floats[3]);
+ return;
+ case VKVG_CMD_ARC:
+ vkvg_arc(ctx, floats[0], floats[1], floats[2], floats[3], floats[4]);
+ return;
+ case VKVG_CMD_ARC_NEG:
+ vkvg_arc(ctx, floats[0], floats[1], floats[2], floats[3], floats[4]);
+ return;
+ /*case VKVG_CMD_ELLIPSE:
+ vkvg_ellipse (ctx, floats[0], floats[1], floats[2], floats[3], floats[4]);
+ break;*/
+ case VKVG_CMD_MOVE_TO:
+ vkvg_move_to(ctx, floats[0], floats[1]);
+ return;
+ case VKVG_CMD_LINE_TO:
+ vkvg_line_to(ctx, floats[0], floats[1]);
+ return;
+ case VKVG_CMD_CURVE_TO:
+ vkvg_curve_to(ctx, floats[0], floats[1], floats[2], floats[3], floats[4], floats[5]);
+ return;
+ case VKVG_CMD_ELLIPTICAL_ARC_TO: {
+ bool *flags = (bool *)&floats[5];
+ vkvg_elliptic_arc_to(ctx, floats[0], floats[1], flags[0], flags[1], floats[2], floats[3], floats[4]);
+ }
+ return;
+ case VKVG_CMD_QUADRATIC_TO:
+ vkvg_quadratic_to(ctx, floats[0], floats[1], floats[2], floats[3]);
+ return;
+ }
+ }
+ } else if (r->cmd & VKVG_CMD_DRAW_COMMANDS) {
+ switch (r->cmd) {
+ case VKVG_CMD_PAINT:
+ vkvg_paint(ctx);
+ return;
+ case VKVG_CMD_FILL:
+ vkvg_fill(ctx);
+ return;
+ case VKVG_CMD_STROKE:
+ vkvg_stroke(ctx);
+ return;
+ case VKVG_CMD_CLIP:
+ vkvg_clip(ctx);
+ return;
+ case VKVG_CMD_CLEAR:
+ vkvg_clear(ctx);
+ return;
+ case VKVG_CMD_FILL_PRESERVE:
+ vkvg_fill_preserve(ctx);
+ return;
+ case VKVG_CMD_STROKE_PRESERVE:
+ vkvg_stroke_preserve(ctx);
+ return;
+ case VKVG_CMD_CLIP_PRESERVE:
+ vkvg_clip_preserve(ctx);
+ return;
+ }
+ } else if (r->cmd & VKVG_CMD_TRANSFORM_COMMANDS) {
+ switch (r->cmd) {
+ case VKVG_CMD_TRANSLATE:
+ vkvg_translate(ctx, floats[0], floats[1]);
+ return;
+ case VKVG_CMD_SCALE:
+ vkvg_scale(ctx, floats[0], floats[1]);
+ return;
+ case VKVG_CMD_ROTATE:
+ vkvg_rotate(ctx, floats[0]);
+ return;
+ case VKVG_CMD_IDENTITY_MATRIX:
+ vkvg_identity_matrix(ctx);
+ return;
+ case VKVG_CMD_TRANSFORM: {
+ vkvg_matrix_t *mat = (vkvg_matrix_t *)&floats[0];
+ vkvg_transform(ctx, mat);
+ }
+ return;
+ case VKVG_CMD_SET_MATRIX: {
+ vkvg_matrix_t *mat = (vkvg_matrix_t *)&floats[0];
+ vkvg_set_matrix(ctx, mat);
+ }
+ return;
+ }
+ } else if (r->cmd & VKVG_CMD_PATTERN_COMMANDS) {
+ switch (r->cmd) {
+ case VKVG_CMD_SET_SOURCE_RGB:
+ vkvg_set_source_rgb(ctx, floats[0], floats[1], floats[2]);
+ return;
+ case VKVG_CMD_SET_SOURCE_RGBA:
+ vkvg_set_source_rgba(ctx, floats[0], floats[1], floats[2], floats[3]);
+ return;
+ case VKVG_CMD_SET_SOURCE_COLOR:
+ vkvg_set_source_color(ctx, uints[0]);
+ return;
+ case VKVG_CMD_SET_SOURCE: {
+ VkvgPattern pat = *((VkvgPattern *)(rec->buffer + r->dataOffset));
+ vkvg_set_source(ctx, pat);
+ }
+ return;
+ case VKVG_CMD_SET_SOURCE_SURFACE: {
+ VkvgSurface surf = *((VkvgSurface *)&floats[2]);
+ vkvg_set_source_surface(ctx, surf, floats[0], floats[1]);
+ }
+ return;
+ }
+ } else if (r->cmd & VKVG_CMD_TEXT_COMMANDS) {
+ char *txt = (char *)floats;
+ switch (r->cmd) {
+ case VKVG_CMD_SET_FONT_SIZE:
+ vkvg_set_font_size(ctx, uints[0]);
+ return;
+ case VKVG_CMD_SET_FONT_FACE:
+ vkvg_select_font_face(ctx, txt);
+ return;
+ /*case VKVG_CMD_SET_FONT_PATH:
+ vkvg_load_font_from_path (ctx, txt);
+ return; */
+ case VKVG_CMD_SHOW_TEXT:
+ vkvg_show_text(ctx, txt);
+ return;
+ }
+ } else {
+ switch (r->cmd) {
+ case VKVG_CMD_SAVE:
+ vkvg_save(ctx);
+ return;
+ case VKVG_CMD_RESTORE:
+ vkvg_restore(ctx);
+ return;
+ }
+ }
+ LOG(VKVG_LOG_ERR, "[REPLAY] unimplemented command: %.4x\n", r->cmd);
}
-
#include "vkvg.h"
#include "vkvg_internal.h"
-#define VKVG_CMD_SAVE 0x0001
-#define VKVG_CMD_RESTORE 0x0002
-
-#define VKVG_CMD_PATH_COMMANDS 0x0100
-#define VKVG_CMD_DRAW_COMMANDS 0x0200
-#define VKVG_CMD_RELATIVE_COMMANDS (0x0400|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_PATHPROPS_COMMANDS (0x1000|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_PRESERVE_COMMANDS (0x0400|VKVG_CMD_DRAW_COMMANDS)
-#define VKVG_CMD_PATTERN_COMMANDS 0x0800
-#define VKVG_CMD_TRANSFORM_COMMANDS 0x2000
-#define VKVG_CMD_TEXT_COMMANDS 0x4000
-
-#define VKVG_CMD_NEW_PATH (0x0001|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_NEW_SUB_PATH (0x0002|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_CLOSE_PATH (0x0003|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_MOVE_TO (0x0004|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_LINE_TO (0x0005|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_RECTANGLE (0x0006|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_ARC (0x0007|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_ARC_NEG (0x0008|VKVG_CMD_PATH_COMMANDS)
-//#define VKVG_CMD_ELLIPSE (0x0009|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_CURVE_TO (0x000A|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_QUADRATIC_TO (0x000B|VKVG_CMD_PATH_COMMANDS)
-#define VKVG_CMD_ELLIPTICAL_ARC_TO (0x000C|VKVG_CMD_PATH_COMMANDS)
-
-#define VKVG_CMD_SET_LINE_WIDTH (0x0001|VKVG_CMD_PATHPROPS_COMMANDS)
-#define VKVG_CMD_SET_MITER_LIMIT (0x0002|VKVG_CMD_PATHPROPS_COMMANDS)
-#define VKVG_CMD_SET_LINE_JOIN (0x0003|VKVG_CMD_PATHPROPS_COMMANDS)
-#define VKVG_CMD_SET_LINE_CAP (0x0004|VKVG_CMD_PATHPROPS_COMMANDS)
-#define VKVG_CMD_SET_OPERATOR (0x0005|VKVG_CMD_PATHPROPS_COMMANDS)
-#define VKVG_CMD_SET_FILL_RULE (0x0006|VKVG_CMD_PATHPROPS_COMMANDS)
-#define VKVG_CMD_SET_DASH (0x0007|VKVG_CMD_PATHPROPS_COMMANDS)
-
-#define VKVG_CMD_TRANSLATE (0x0001|VKVG_CMD_TRANSFORM_COMMANDS)
-#define VKVG_CMD_ROTATE (0x0002|VKVG_CMD_TRANSFORM_COMMANDS)
-#define VKVG_CMD_SCALE (0x0003|VKVG_CMD_TRANSFORM_COMMANDS)
-#define VKVG_CMD_TRANSFORM (0x0004|VKVG_CMD_TRANSFORM_COMMANDS)
-#define VKVG_CMD_IDENTITY_MATRIX (0x0005|VKVG_CMD_TRANSFORM_COMMANDS)
-
-#define VKVG_CMD_SET_MATRIX (0x0006|VKVG_CMD_TRANSFORM_COMMANDS)
-
-#define VKVG_CMD_SET_FONT_SIZE (0x0001|VKVG_CMD_TEXT_COMMANDS)
-#define VKVG_CMD_SET_FONT_FACE (0x0002|VKVG_CMD_TEXT_COMMANDS)
-#define VKVG_CMD_SET_FONT_PATH (0x0003|VKVG_CMD_TEXT_COMMANDS)
-#define VKVG_CMD_SHOW_TEXT (0x0004|VKVG_CMD_TEXT_COMMANDS)
-
-#define VKVG_CMD_REL_MOVE_TO (VKVG_CMD_MOVE_TO |VKVG_CMD_RELATIVE_COMMANDS)
-#define VKVG_CMD_REL_LINE_TO (VKVG_CMD_LINE_TO |VKVG_CMD_RELATIVE_COMMANDS)
-#define VKVG_CMD_REL_CURVE_TO (VKVG_CMD_CURVE_TO |VKVG_CMD_RELATIVE_COMMANDS)
-#define VKVG_CMD_REL_QUADRATIC_TO (VKVG_CMD_QUADRATIC_TO |VKVG_CMD_RELATIVE_COMMANDS)
-#define VKVG_CMD_REL_ELLIPTICAL_ARC_TO (VKVG_CMD_ELLIPTICAL_ARC_TO |VKVG_CMD_RELATIVE_COMMANDS)
-
-#define VKVG_CMD_PAINT (0x0001|VKVG_CMD_DRAW_COMMANDS)
-#define VKVG_CMD_FILL (0x0002|VKVG_CMD_DRAW_COMMANDS)
-#define VKVG_CMD_STROKE (0x0003|VKVG_CMD_DRAW_COMMANDS)
-#define VKVG_CMD_CLIP (0x0004|VKVG_CMD_DRAW_COMMANDS)
-#define VKVG_CMD_RESET_CLIP (0x0005|VKVG_CMD_DRAW_COMMANDS)
-#define VKVG_CMD_CLEAR (0x0006|VKVG_CMD_DRAW_COMMANDS)
-
-#define VKVG_CMD_FILL_PRESERVE (VKVG_CMD_FILL |VKVG_CMD_PRESERVE_COMMANDS)
-#define VKVG_CMD_STROKE_PRESERVE (VKVG_CMD_STROKE |VKVG_CMD_PRESERVE_COMMANDS)
-#define VKVG_CMD_CLIP_PRESERVE (VKVG_CMD_CLIP |VKVG_CMD_PRESERVE_COMMANDS)
-
-#define VKVG_CMD_SET_SOURCE_RGB (0x0001|VKVG_CMD_PATTERN_COMMANDS)
-#define VKVG_CMD_SET_SOURCE_RGBA (0x0002|VKVG_CMD_PATTERN_COMMANDS)
-#define VKVG_CMD_SET_SOURCE_COLOR (0x0003|VKVG_CMD_PATTERN_COMMANDS)
-#define VKVG_CMD_SET_SOURCE (0x0004|VKVG_CMD_PATTERN_COMMANDS)
-#define VKVG_CMD_SET_SOURCE_SURFACE (0x0005|VKVG_CMD_PATTERN_COMMANDS)
-
-
-
-typedef struct _vkvg_record_t{
- uint16_t cmd;
- size_t dataOffset;
-}vkvg_record_t;
-
-typedef struct _vkvg_recording_t{
- vkvg_record_t* commands;
- uint32_t commandsCount;
- uint32_t commandsReservedCount;
- size_t bufferSize;
- size_t bufferReservedSize;
- char* buffer;
-}vkvg_recording_t;
-
-
-void _start_recording (VkvgContext ctx);
-vkvg_recording_t* _stop_recording (VkvgContext ctx);
-void _destroy_recording (vkvg_recording_t* rec);
-void _replay_command (VkvgContext ctx, VkvgRecording rec, uint32_t index);
-void _record (vkvg_recording_t* rec,...);
-
-#define RECORD(ctx,...) {\
- if (ctx->recording) {\
- _record (ctx->recording,__VA_ARGS__);\
- return;\
- }\
-}
-#define RECORD2(ctx,...) {\
- if (ctx->recording) {\
- _record (ctx->recording,__VA_ARGS__);\
- return 0;\
- }\
-}
-
+#define VKVG_CMD_SAVE 0x0001
+#define VKVG_CMD_RESTORE 0x0002
+
+#define VKVG_CMD_PATH_COMMANDS 0x0100
+#define VKVG_CMD_DRAW_COMMANDS 0x0200
+#define VKVG_CMD_RELATIVE_COMMANDS (0x0400 | VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_PATHPROPS_COMMANDS (0x1000 | VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_PRESERVE_COMMANDS (0x0400 | VKVG_CMD_DRAW_COMMANDS)
+#define VKVG_CMD_PATTERN_COMMANDS 0x0800
+#define VKVG_CMD_TRANSFORM_COMMANDS 0x2000
+#define VKVG_CMD_TEXT_COMMANDS 0x4000
+
+#define VKVG_CMD_NEW_PATH (0x0001 | VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_NEW_SUB_PATH (0x0002 | VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_CLOSE_PATH (0x0003 | VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_MOVE_TO (0x0004 | VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_LINE_TO (0x0005 | VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_RECTANGLE (0x0006 | VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_ARC (0x0007 | VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_ARC_NEG (0x0008 | VKVG_CMD_PATH_COMMANDS)
+// #define VKVG_CMD_ELLIPSE (0x0009|VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_CURVE_TO (0x000A | VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_QUADRATIC_TO (0x000B | VKVG_CMD_PATH_COMMANDS)
+#define VKVG_CMD_ELLIPTICAL_ARC_TO (0x000C | VKVG_CMD_PATH_COMMANDS)
+
+#define VKVG_CMD_SET_LINE_WIDTH (0x0001 | VKVG_CMD_PATHPROPS_COMMANDS)
+#define VKVG_CMD_SET_MITER_LIMIT (0x0002 | VKVG_CMD_PATHPROPS_COMMANDS)
+#define VKVG_CMD_SET_LINE_JOIN (0x0003 | VKVG_CMD_PATHPROPS_COMMANDS)
+#define VKVG_CMD_SET_LINE_CAP (0x0004 | VKVG_CMD_PATHPROPS_COMMANDS)
+#define VKVG_CMD_SET_OPERATOR (0x0005 | VKVG_CMD_PATHPROPS_COMMANDS)
+#define VKVG_CMD_SET_FILL_RULE (0x0006 | VKVG_CMD_PATHPROPS_COMMANDS)
+#define VKVG_CMD_SET_DASH (0x0007 | VKVG_CMD_PATHPROPS_COMMANDS)
+
+#define VKVG_CMD_TRANSLATE (0x0001 | VKVG_CMD_TRANSFORM_COMMANDS)
+#define VKVG_CMD_ROTATE (0x0002 | VKVG_CMD_TRANSFORM_COMMANDS)
+#define VKVG_CMD_SCALE (0x0003 | VKVG_CMD_TRANSFORM_COMMANDS)
+#define VKVG_CMD_TRANSFORM (0x0004 | VKVG_CMD_TRANSFORM_COMMANDS)
+#define VKVG_CMD_IDENTITY_MATRIX (0x0005 | VKVG_CMD_TRANSFORM_COMMANDS)
+
+#define VKVG_CMD_SET_MATRIX (0x0006 | VKVG_CMD_TRANSFORM_COMMANDS)
+
+#define VKVG_CMD_SET_FONT_SIZE (0x0001 | VKVG_CMD_TEXT_COMMANDS)
+#define VKVG_CMD_SET_FONT_FACE (0x0002 | VKVG_CMD_TEXT_COMMANDS)
+#define VKVG_CMD_SET_FONT_PATH (0x0003 | VKVG_CMD_TEXT_COMMANDS)
+#define VKVG_CMD_SHOW_TEXT (0x0004 | VKVG_CMD_TEXT_COMMANDS)
+
+#define VKVG_CMD_REL_MOVE_TO (VKVG_CMD_MOVE_TO | VKVG_CMD_RELATIVE_COMMANDS)
+#define VKVG_CMD_REL_LINE_TO (VKVG_CMD_LINE_TO | VKVG_CMD_RELATIVE_COMMANDS)
+#define VKVG_CMD_REL_CURVE_TO (VKVG_CMD_CURVE_TO | VKVG_CMD_RELATIVE_COMMANDS)
+#define VKVG_CMD_REL_QUADRATIC_TO (VKVG_CMD_QUADRATIC_TO | VKVG_CMD_RELATIVE_COMMANDS)
+#define VKVG_CMD_REL_ELLIPTICAL_ARC_TO (VKVG_CMD_ELLIPTICAL_ARC_TO | VKVG_CMD_RELATIVE_COMMANDS)
+
+#define VKVG_CMD_PAINT (0x0001 | VKVG_CMD_DRAW_COMMANDS)
+#define VKVG_CMD_FILL (0x0002 | VKVG_CMD_DRAW_COMMANDS)
+#define VKVG_CMD_STROKE (0x0003 | VKVG_CMD_DRAW_COMMANDS)
+#define VKVG_CMD_CLIP (0x0004 | VKVG_CMD_DRAW_COMMANDS)
+#define VKVG_CMD_RESET_CLIP (0x0005 | VKVG_CMD_DRAW_COMMANDS)
+#define VKVG_CMD_CLEAR (0x0006 | VKVG_CMD_DRAW_COMMANDS)
+
+#define VKVG_CMD_FILL_PRESERVE (VKVG_CMD_FILL | VKVG_CMD_PRESERVE_COMMANDS)
+#define VKVG_CMD_STROKE_PRESERVE (VKVG_CMD_STROKE | VKVG_CMD_PRESERVE_COMMANDS)
+#define VKVG_CMD_CLIP_PRESERVE (VKVG_CMD_CLIP | VKVG_CMD_PRESERVE_COMMANDS)
+
+#define VKVG_CMD_SET_SOURCE_RGB (0x0001 | VKVG_CMD_PATTERN_COMMANDS)
+#define VKVG_CMD_SET_SOURCE_RGBA (0x0002 | VKVG_CMD_PATTERN_COMMANDS)
+#define VKVG_CMD_SET_SOURCE_COLOR (0x0003 | VKVG_CMD_PATTERN_COMMANDS)
+#define VKVG_CMD_SET_SOURCE (0x0004 | VKVG_CMD_PATTERN_COMMANDS)
+#define VKVG_CMD_SET_SOURCE_SURFACE (0x0005 | VKVG_CMD_PATTERN_COMMANDS)
+
+typedef struct _vkvg_record_t {
+ uint16_t cmd;
+ size_t dataOffset;
+} vkvg_record_t;
+
+typedef struct _vkvg_recording_t {
+ vkvg_record_t *commands;
+ uint32_t commandsCount;
+ uint32_t commandsReservedCount;
+ size_t bufferSize;
+ size_t bufferReservedSize;
+ char *buffer;
+} vkvg_recording_t;
+
+void _start_recording(VkvgContext ctx);
+vkvg_recording_t *_stop_recording(VkvgContext ctx);
+void _destroy_recording(vkvg_recording_t *rec);
+void _replay_command(VkvgContext ctx, VkvgRecording rec, uint32_t index);
+void _record(vkvg_recording_t *rec, ...);
+
+#define RECORD(ctx, ...) \
+ { \
+ if (ctx->recording) { \
+ _record(ctx->recording, __VA_ARGS__); \
+ return; \
+ } \
+ }
+#define RECORD2(ctx, ...) \
+ { \
+ if (ctx->recording) { \
+ _record(ctx->recording, __VA_ARGS__); \
+ return 0; \
+ } \
+ }
#endif
unsigned char shader_comp_spv[] = {
- 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00,
- 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
- 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0xc2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41,
- 0x52, 0x42, 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f,
- 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63,
- 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f, 0x47,
- 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74,
- 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x69, 0x72,
- 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
- 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e,
- 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
- 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61,
- 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49,
- 0x44, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x1f, 0x00, 0x00, 0x00,
- 0x78, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0x79, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x2d, 0x00, 0x00, 0x00,
- 0x75, 0x76, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x31, 0x00, 0x00, 0x00,
- 0x6e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x00,
- 0x63, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x3d, 0x00, 0x00, 0x00,
- 0x7a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00,
- 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x6d, 0x00, 0x00, 0x00,
- 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x73, 0x00, 0x00, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x76, 0x00, 0x00, 0x00,
- 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7b, 0x00, 0x00, 0x00,
- 0x66, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x00, 0x00,
- 0x67, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x84, 0x00, 0x00, 0x00,
- 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0x97, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
- 0x97, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0xa0, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0x80, 0x0c, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
- 0x60, 0x09, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x45,
- 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x16, 0x45, 0x17, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0xe3, 0xbe, 0x2c, 0x00, 0x05, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x2b, 0x00, 0x04, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x8f, 0xc2, 0x15, 0x40,
- 0x2c, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
- 0x3f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3f, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x3f, 0x00, 0x00, 0x00,
- 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x3f, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x2b, 0x00, 0x04, 0x00,
- 0x3f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x43, 0x17, 0x00, 0x04, 0x00, 0x71, 0x00, 0x00, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
- 0x9a, 0x99, 0x99, 0x3e, 0x2c, 0x00, 0x06, 0x00, 0x71, 0x00, 0x00, 0x00,
- 0x75, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x77, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x4c, 0xbe, 0x2b, 0x00, 0x04, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x99, 0xbe,
- 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xbf, 0x2c, 0x00, 0x06, 0x00, 0x71, 0x00, 0x00, 0x00,
- 0x7a, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
- 0x79, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x7c, 0x00, 0x00, 0x00, 0x66, 0x66, 0x06, 0x40, 0x2b, 0x00, 0x04, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40,
- 0x2c, 0x00, 0x06, 0x00, 0x71, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
- 0x7c, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0xcd, 0xcc, 0xcc, 0x3d, 0x2c, 0x00, 0x06, 0x00, 0x71, 0x00, 0x00, 0x00,
- 0x81, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x82, 0x00, 0x00, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x83, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00,
- 0xd0, 0x0f, 0xc9, 0x40, 0x19, 0x00, 0x09, 0x00, 0x95, 0x00, 0x00, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x96, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x96, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x04, 0x00, 0x99, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x9c, 0x00, 0x00, 0x00,
- 0x3f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
- 0x9f, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x1f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x72, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x76, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x72, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x83, 0x00, 0x00, 0x00,
- 0x84, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xae, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00,
- 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
- 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x12, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0xae, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x07, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
- 0xf7, 0x00, 0x03, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfa, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0x1b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0xfd, 0x00, 0x01, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x1b, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x70, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
- 0x70, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x27, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x2a, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
- 0x1f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x2d, 0x00, 0x00, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x31, 0x00, 0x00, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x36, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x39, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x8e, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
- 0x39, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x00,
- 0x3c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3d, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00,
- 0x42, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x43, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x43, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00,
- 0x45, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf9, 0x00, 0x02, 0x00, 0x47, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x47, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x3f, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
- 0x49, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00,
- 0x44, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x44, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x4b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x4b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x4d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00,
- 0x4d, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x4f, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x51, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
- 0x54, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x57, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x57, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x59, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x59, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x5e, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00,
- 0x5e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3d, 0x00, 0x00, 0x00,
- 0x5f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x60, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
- 0x94, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00,
- 0x60, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x65, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x63, 0x00, 0x00, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x45, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
- 0x81, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
- 0x67, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0x46, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x46, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x3f, 0x00, 0x00, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
- 0xf9, 0x00, 0x02, 0x00, 0x43, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x45, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x6e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00,
- 0x6f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x6d, 0x00, 0x00, 0x00,
- 0x70, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x73, 0x00, 0x00, 0x00,
- 0x75, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x76, 0x00, 0x00, 0x00,
- 0x7a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7b, 0x00, 0x00, 0x00,
- 0x7e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x00, 0x00,
- 0x81, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x71, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x71, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x71, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
- 0x7b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x89, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x05, 0x00,
- 0x71, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
- 0x89, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x71, 0x00, 0x00, 0x00,
- 0x8b, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x71, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00,
- 0x8b, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x05, 0x00, 0x71, 0x00, 0x00, 0x00,
- 0x8d, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x06, 0x00, 0x71, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x71, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00,
- 0x86, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x71, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00,
- 0x8f, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x91, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x51, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00,
- 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x82, 0x00, 0x00, 0x00,
- 0x94, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00,
- 0x93, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x84, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x95, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x99, 0x00, 0x00, 0x00,
- 0x9b, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00,
- 0x9c, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x82, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
- 0x84, 0x00, 0x00, 0x00, 0x63, 0x00, 0x04, 0x00, 0x98, 0x00, 0x00, 0x00,
- 0x9d, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
- 0x38, 0x00, 0x01, 0x00
-};
-unsigned int shader_comp_spv_len = 3580;
-unsigned char shader2_comp_spv[] = {
- 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
- 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0xc2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41,
- 0x52, 0x42, 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f,
- 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63,
- 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f, 0x47,
- 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74,
- 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x69, 0x72,
- 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
- 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e,
- 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
- 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x28, 0x76, 0x66, 0x32, 0x3b, 0x76, 0x66, 0x32,
- 0x3b, 0x76, 0x66, 0x32, 0x3b, 0x66, 0x31, 0x3b, 0x66, 0x31, 0x3b, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x75, 0x76, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x70, 0x6f, 0x73, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0x74, 0x68, 0x69, 0x63, 0x6b, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x12, 0x00, 0x00, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76,
- 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x70, 0x6f, 0x73, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61,
- 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x52, 0x00, 0x00, 0x00,
- 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x53, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x54, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61,
- 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x55, 0x00, 0x00, 0x00,
- 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x59, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x61, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x33, 0x33, 0x73, 0x3f,
- 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
- 0xcd, 0xcc, 0x4c, 0x3d, 0x14, 0x00, 0x02, 0x00, 0x27, 0x00, 0x00, 0x00,
- 0x15, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x2d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x80, 0x0c, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x35, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x48, 0x45, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x45, 0x2b, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x19, 0x3f,
- 0x2c, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x4b, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0xcc, 0x3d,
- 0x2c, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00,
- 0x4d, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x6f, 0x12, 0x03, 0x3b,
- 0x17, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
- 0x5f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x60, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x63, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
- 0x66, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x04, 0x00, 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x6a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x06, 0x00,
- 0x29, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
- 0x6a, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x4a, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x53, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x59, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0xae, 0x00, 0x05, 0x00,
- 0x27, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x33, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x2d, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x35, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xae, 0x00, 0x05, 0x00,
- 0x27, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x34, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x34, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x07, 0x00,
- 0x27, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
- 0xf7, 0x00, 0x03, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfa, 0x00, 0x04, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
- 0x3c, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x3b, 0x00, 0x00, 0x00,
- 0xfd, 0x00, 0x01, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
- 0x70, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x43, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
- 0x70, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
- 0x45, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00,
- 0x43, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x3e, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x52, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x53, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x55, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
- 0x39, 0x00, 0x09, 0x00, 0x06, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
- 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
- 0x4a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x5b, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00,
- 0x4a, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x57, 0x00, 0x00, 0x00,
- 0x5e, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x59, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x5f, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x63, 0x00, 0x00, 0x00,
- 0x65, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00,
- 0x67, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
- 0x59, 0x00, 0x00, 0x00, 0x63, 0x00, 0x04, 0x00, 0x62, 0x00, 0x00, 0x00,
- 0x68, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
- 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x1a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x12, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0xfe, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00
-};
-unsigned int shader2_comp_spv_len = 2604;
+ 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
+ 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52,
+ 0x42, 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f,
+ 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47,
+ 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f,
+ 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49,
+ 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x1f,
+ 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x03, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x75, 0x76, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x31, 0x00, 0x00,
+ 0x00, 0x6e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x03, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00, 0x69,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
+ 0x73, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x76, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x03, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00,
+ 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x84, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x97, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x00, 0x47, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00,
+ 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, 0x21, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x97, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x47,
+ 0x00, 0x04, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x80,
+ 0x0c, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x2b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x16, 0x00, 0x03,
+ 0x00, 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x07, 0x00,
+ 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x48, 0x45, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x45,
+ 0x17, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04,
+ 0x00, 0x2c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00,
+ 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x34,
+ 0x00, 0x00, 0x00, 0x0a, 0xd7, 0xe3, 0xbe, 0x2c, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3f, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x8f, 0xc2,
+ 0x15, 0x40, 0x2c, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04,
+ 0x00, 0x3f, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x3f, 0x00,
+ 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x56,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x2b, 0x00, 0x04, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x17, 0x00,
+ 0x04, 0x00, 0x71, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x72,
+ 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x99, 0x3e, 0x2c, 0x00, 0x06, 0x00, 0x71, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00,
+ 0x00, 0x74, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00,
+ 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x4c, 0xbe, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x78,
+ 0x00, 0x00, 0x00, 0x9a, 0x99, 0x99, 0xbe, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xbf, 0x2c, 0x00, 0x06, 0x00, 0x71, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00,
+ 0x00, 0x78, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x7c, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x06, 0x40, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x40, 0x2c, 0x00, 0x06, 0x00, 0x71, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0x56, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0xcd, 0xcc, 0xcc, 0x3d, 0x2c, 0x00, 0x06, 0x00, 0x71, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x32, 0x00,
+ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x82, 0x00, 0x00, 0x00, 0x1d,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x83, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x82, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0xd0, 0x0f, 0xc9,
+ 0x40, 0x19, 0x00, 0x09, 0x00, 0x95, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x04, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+ 0x96, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x99, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x3f, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x2c, 0x00, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00,
+ 0x9f, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00,
+ 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1e,
+ 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x2d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x07, 0x00,
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b,
+ 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x72, 0x00, 0x00,
+ 0x00, 0x73, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x72, 0x00, 0x00, 0x00, 0x76, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x72, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x72, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x3b, 0x00, 0x04, 0x00, 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05,
+ 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xae, 0x00, 0x05, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x04, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00,
+ 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x12, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x15,
+ 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0xae, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+ 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf8, 0x00,
+ 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00,
+ 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00,
+ 0x00, 0x1b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0xf8, 0x00,
+ 0x02, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0a,
+ 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00,
+ 0x00, 0x88, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00,
+ 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0c,
+ 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x2a, 0x00,
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00, 0x2a,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05,
+ 0x00, 0x2b, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x3e, 0x00,
+ 0x03, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
+ 0x50, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00,
+ 0x00, 0x83, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x38, 0x00,
+ 0x00, 0x00, 0x8e, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3a,
+ 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
+ 0x3b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03,
+ 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00, 0x42, 0x00,
+ 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x43, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x43, 0x00, 0x00, 0x00, 0xf6,
+ 0x00, 0x04, 0x00, 0x45, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
+ 0x47, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x47, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x3f, 0x00, 0x00,
+ 0x00, 0x48, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4a, 0x00,
+ 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x44,
+ 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x44, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04,
+ 0x00, 0x1d, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00,
+ 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d,
+ 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00,
+ 0x4f, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00, 0x00,
+ 0x00, 0x50, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00,
+ 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x52,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
+ 0x53, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00,
+ 0x00, 0x51, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x55, 0x00,
+ 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x57,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00,
+ 0x00, 0x56, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x5a, 0x00,
+ 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x59, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00,
+ 0x00, 0x55, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x5e, 0x00,
+ 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x5d,
+ 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04,
+ 0x00, 0x2b, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x94, 0x00, 0x05, 0x00, 0x1d, 0x00,
+ 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00,
+ 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x63, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00,
+ 0x00, 0x65, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x45, 0x00,
+ 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x67,
+ 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
+ 0x67, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x31, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00,
+ 0x00, 0xf9, 0x00, 0x02, 0x00, 0x46, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x46, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x3f,
+ 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+ 0x41, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x43, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02,
+ 0x00, 0x45, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x31, 0x00,
+ 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x6f,
+ 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+ 0x73, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x76, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00,
+ 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7f, 0x00,
+ 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x71, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x73,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x71, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x71, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04,
+ 0x00, 0x1d, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x05, 0x00, 0x71, 0x00,
+ 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x71,
+ 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x71, 0x00, 0x00, 0x00,
+ 0x8c, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x05, 0x00, 0x71, 0x00, 0x00,
+ 0x00, 0x8d, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x71, 0x00,
+ 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x85,
+ 0x00, 0x05, 0x00, 0x71, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
+ 0x81, 0x00, 0x05, 0x00, 0x71, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00,
+ 0x00, 0x51, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x82, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00,
+ 0x00, 0x92, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x84, 0x00,
+ 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x95, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x97,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x4f, 0x00, 0x07, 0x00, 0x99, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x9d, 0x00,
+ 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x82, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x84,
+ 0x00, 0x00, 0x00, 0x63, 0x00, 0x04, 0x00, 0x98, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
+ 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
+unsigned int shader_comp_spv_len = 3580;
+unsigned char shader2_comp_spv[] = {
+ 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
+ 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52,
+ 0x42, 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f,
+ 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47,
+ 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f,
+ 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x46, 0x72, 0x61,
+ 0x6d, 0x65, 0x28, 0x76, 0x66, 0x32, 0x3b, 0x76, 0x66, 0x32, 0x3b, 0x76, 0x66, 0x32, 0x3b, 0x66, 0x31, 0x3b, 0x66,
+ 0x31, 0x3b, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x75, 0x76, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x70, 0x6f, 0x73, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a,
+ 0x65, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73,
+ 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x74, 0x68, 0x69, 0x63, 0x6b, 0x6e, 0x65, 0x73, 0x73,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x12, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00,
+ 0x2b, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x70, 0x6f,
+ 0x73, 0x00, 0x05, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x50,
+ 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x52, 0x00, 0x00, 0x00,
+ 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x53, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72,
+ 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x54, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x55, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05,
+ 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
+ 0x61, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
+ 0x00, 0x1c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x00, 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6b, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x33,
+ 0x33, 0x73, 0x3f, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x4c, 0x3d,
+ 0x14, 0x00, 0x02, 0x00, 0x27, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x3b,
+ 0x00, 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2d, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0x80, 0x0c, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00,
+ 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x45, 0x2b, 0x00, 0x04,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x45, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x19, 0x3f, 0x2c, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x4c,
+ 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x4d, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0xcc, 0x3d, 0x2c, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00,
+ 0x00, 0x4d, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4f, 0x00,
+ 0x00, 0x00, 0x6f, 0x12, 0x03, 0x3b, 0x17, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
+ 0x19, 0x00, 0x09, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x04, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x60,
+ 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x63, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x66, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2c,
+ 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
+ 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a,
+ 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00,
+ 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x09,
+ 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x59, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00,
+ 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2f, 0x00,
+ 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0xae, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x2f,
+ 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x31, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04,
+ 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x33, 0x00,
+ 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x35,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
+ 0xae, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00,
+ 0x00, 0xf9, 0x00, 0x02, 0x00, 0x34, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x34, 0x00, 0x00, 0x00, 0xf5, 0x00,
+ 0x07, 0x00, 0x27, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x39,
+ 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfa, 0x00, 0x04, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02,
+ 0x00, 0x3b, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x41, 0x00,
+ 0x05, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3d,
+ 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x43, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2d, 0x00,
+ 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x28,
+ 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x46, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00,
+ 0x00, 0x46, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x49, 0x00,
+ 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x49,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
+ 0x3e, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x52, 0x00, 0x00,
+ 0x00, 0x4c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x53, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x3e, 0x00,
+ 0x03, 0x00, 0x54, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x55, 0x00, 0x00, 0x00, 0x4f,
+ 0x00, 0x00, 0x00, 0x39, 0x00, 0x09, 0x00, 0x06, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x50, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00,
+ 0x00, 0x3e, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x4a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00,
+ 0x00, 0x50, 0x00, 0x07, 0x00, 0x57, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x59, 0x00, 0x00, 0x00, 0x5e,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07,
+ 0x00, 0x63, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00, 0x67, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x65,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
+ 0x63, 0x00, 0x04, 0x00, 0x62, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01,
+ 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x37,
+ 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x0d, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03,
+ 0x00, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3b, 0x00,
+ 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00,
+ 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x16, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00,
+ 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x83, 0x00,
+ 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0c,
+ 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
+ 0x1a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
+ 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00,
+ 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x21, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+ 0x1f, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01,
+ 0x00};
+unsigned int shader2_comp_spv_len = 2604;
unsigned char vkvg_main_frag_spv[] = {
- 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00,
- 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
- 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x00,
- 0x94, 0x01, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0xc2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41,
- 0x52, 0x42, 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f,
- 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63,
- 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41,
- 0x52, 0x42, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6c,
- 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x34, 0x32, 0x30, 0x70,
- 0x61, 0x63, 0x6b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x45,
- 0x58, 0x54, 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x61, 0x72, 0x5f, 0x62, 0x6c,
- 0x6f, 0x63, 0x6b, 0x5f, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x00, 0x00,
- 0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c,
- 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f,
- 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
- 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47,
- 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64,
- 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x63, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x69, 0x6e, 0x53, 0x72, 0x63, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x50, 0x61, 0x74, 0x54, 0x79, 0x70,
- 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00,
- 0x70, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x75, 0x76, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x4a, 0x00, 0x00, 0x00, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x52, 0x00, 0x00, 0x00, 0x64, 0x69, 0x73, 0x74,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x70, 0x30, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00,
- 0x5f, 0x75, 0x62, 0x6f, 0x47, 0x72, 0x61, 0x64, 0x00, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00,
- 0x5a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x74, 0x6f, 0x70,
- 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x63, 0x70, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00,
- 0x5a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x75, 0x6e,
- 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x75, 0x62, 0x6f, 0x47, 0x72, 0x61, 0x64, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x70, 0x31, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0x70, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0x75, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0x97, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0x9e, 0x00, 0x00, 0x00, 0x62, 0x62, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0xcc, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0xf2, 0x00, 0x00, 0x00, 0x63, 0x30, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0xf9, 0x00, 0x00, 0x00, 0x63, 0x31, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0x00, 0x01, 0x00, 0x00, 0x72, 0x30, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0x06, 0x01, 0x00, 0x00, 0x72, 0x31, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
- 0x0c, 0x01, 0x00, 0x00, 0x67, 0x72, 0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67,
- 0x74, 0x68, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0d, 0x01, 0x00, 0x00,
- 0x64, 0x69, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x11, 0x01, 0x00, 0x00, 0x72, 0x61, 0x79, 0x44, 0x69, 0x72, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x16, 0x01, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x20, 0x01, 0x00, 0x00, 0x63, 0x63, 0x00, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x28, 0x01, 0x00, 0x00, 0x64, 0x69, 0x73, 0x63,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x36, 0x01, 0x00, 0x00,
- 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x40, 0x01, 0x00, 0x00,
- 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x4b, 0x01, 0x00, 0x00, 0x67, 0x72, 0x61, 0x64,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x5f, 0x01, 0x00, 0x00,
- 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x7f, 0x01, 0x00, 0x00,
- 0x69, 0x6e, 0x46, 0x6f, 0x6e, 0x74, 0x55, 0x56, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x88, 0x01, 0x00, 0x00, 0x66, 0x6f, 0x6e, 0x74,
- 0x4d, 0x61, 0x70, 0x00, 0x05, 0x00, 0x05, 0x00, 0x8f, 0x01, 0x00, 0x00,
- 0x69, 0x6e, 0x4f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x06, 0x00, 0x94, 0x01, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x46,
- 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x05, 0x00, 0x96, 0x01, 0x00, 0x00, 0x4e, 0x55, 0x4d, 0x5f,
- 0x53, 0x41, 0x4d, 0x50, 0x4c, 0x45, 0x53, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
- 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x48, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
- 0x5a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0x60, 0x01, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x5a, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x88, 0x01, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x88, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x03, 0x00, 0x8f, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x8f, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x94, 0x01, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x96, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x15, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
- 0x47, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x49, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x2b, 0x00, 0x04, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x55, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x58, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, 0x5a, 0x00, 0x00, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x5b, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x5b, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00,
- 0x7d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xc2, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0xcb, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xd5, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x1b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0x40, 0x17, 0x00, 0x04, 0x00, 0x7d, 0x01, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x7e, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7d, 0x01, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x7e, 0x01, 0x00, 0x00, 0x7f, 0x01, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x85, 0x01, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x86, 0x01, 0x00, 0x00,
- 0x85, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x87, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x86, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x87, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x93, 0x01, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x93, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x32, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x96, 0x01, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x97, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0xf2, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x06, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x0d, 0x01, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0x11, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1a, 0x01, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x20, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0x40, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x4b, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
- 0xf7, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfb, 0x00, 0x09, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x12, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0x19, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x1b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
- 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x83, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x1a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x27, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x25, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
- 0x2e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0x35, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x36, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
- 0x36, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x39, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x42, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
- 0x43, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x45, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x4d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
- 0x4d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x88, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
- 0x4f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x5d, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
- 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
- 0x5f, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x61, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00,
- 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x88, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00,
- 0x60, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x54, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x5d, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00,
- 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00,
- 0x66, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x68, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
- 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x88, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
- 0x67, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
- 0x6b, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x6d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00,
- 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x88, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x54, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x73, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x70, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x77, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
- 0x77, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
- 0x78, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x75, 0x00, 0x00, 0x00,
- 0x79, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x7a, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00,
- 0x7a, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x05, 0x00, 0x7d, 0x00, 0x00, 0x00,
- 0x7e, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
- 0xf7, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfa, 0x00, 0x04, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
- 0x96, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00,
- 0x75, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00,
- 0xb8, 0x00, 0x05, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00,
- 0x82, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00,
- 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
- 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x84, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x87, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x89, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00,
- 0x89, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x8b, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
- 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00,
- 0x8b, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x52, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0x85, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x8e, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00,
- 0x54, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00,
- 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00,
- 0x90, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
- 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00,
- 0x93, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x52, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0x85, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x85, 0x00, 0x00, 0x00,
- 0xf9, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x96, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x98, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00,
- 0x98, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x9a, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x9c, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00,
- 0x9c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x97, 0x00, 0x00, 0x00,
- 0x9d, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x9f, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
- 0x9f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xa1, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xa3, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00,
- 0xa3, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xa5, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x9e, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,
- 0x97, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0xa9, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
- 0xa9, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xab, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
- 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00,
- 0xa7, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
- 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00,
- 0xac, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00,
- 0x97, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xb1, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00,
- 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00,
- 0x53, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x1f, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00,
- 0xb3, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xb5, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,
- 0xb5, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x52, 0x00, 0x00, 0x00,
- 0xb6, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0xb7, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00,
- 0xb7, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, 0x7d, 0x00, 0x00, 0x00,
- 0xb9, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
- 0xf7, 0x00, 0x03, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfa, 0x00, 0x04, 0x00, 0xb9, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00,
- 0xbb, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xba, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00,
- 0x52, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xbd, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x52, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0xbb, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xbb, 0x00, 0x00, 0x00,
- 0xf9, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00,
- 0xbe, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0xbf, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x5d, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x06, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00,
- 0xc3, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xc2, 0x00, 0x00, 0x00,
- 0xc5, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xc6, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00,
- 0xc6, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
- 0xc8, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00,
- 0xc1, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0xcc, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0xcd, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00,
- 0xf6, 0x00, 0x04, 0x00, 0xcf, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xd1, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00,
- 0x7c, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00,
- 0xd2, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xd5, 0x00, 0x00, 0x00,
- 0xd6, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00,
- 0xd6, 0x00, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0xd8, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
- 0xb0, 0x00, 0x05, 0x00, 0x7d, 0x00, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00,
- 0xd3, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
- 0xd9, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0xce, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00,
- 0xcc, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0xdc, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00,
- 0xdd, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0xdf, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0xc2, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00,
- 0xcc, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0xe3, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x06, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00,
- 0xe4, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xe6, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00,
- 0xe6, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0xe8, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00,
- 0xe7, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x2e, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00,
- 0xe8, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0xe9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xd0, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00,
- 0xea, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0xcc, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0xcd, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xcf, 0x00, 0x00, 0x00,
- 0xf9, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x13, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0xed, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00,
- 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0xf0, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00,
- 0xf0, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00,
- 0xf1, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00,
- 0xf3, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0xf4, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00,
- 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0xf7, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00,
- 0xf7, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xf2, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00,
- 0xfa, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0xfb, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00,
- 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0xfe, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
- 0xfe, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xf9, 0x00, 0x00, 0x00,
- 0xff, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0xc2, 0x00, 0x00, 0x00,
- 0x01, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00,
- 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00,
- 0x02, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x00, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00,
- 0xc2, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00,
- 0x07, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0x09, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00,
- 0x09, 0x01, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x0b, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x06, 0x01, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
- 0xf2, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x0f, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
- 0x0f, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x0d, 0x01, 0x00, 0x00,
- 0x10, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x12, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00,
- 0x83, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00,
- 0x12, 0x01, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x45, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x11, 0x01, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00,
- 0x11, 0x01, 0x00, 0x00, 0x94, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x19, 0x01, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x16, 0x01, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x00, 0x00,
- 0x11, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x1d, 0x01, 0x00, 0x00, 0x0d, 0x01, 0x00, 0x00, 0x94, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x1c, 0x01, 0x00, 0x00,
- 0x1d, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x1f, 0x01, 0x00, 0x00, 0x1b, 0x01, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x1f, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00,
- 0x0d, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x22, 0x01, 0x00, 0x00, 0x0d, 0x01, 0x00, 0x00, 0x94, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00,
- 0x22, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x24, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00,
- 0x24, 0x01, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00,
- 0x26, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x27, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x29, 0x01, 0x00, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x2a, 0x01, 0x00, 0x00, 0x1a, 0x01, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
- 0x29, 0x01, 0x00, 0x00, 0x2a, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2e, 0x01, 0x00, 0x00,
- 0x2c, 0x01, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x2f, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00,
- 0x2e, 0x01, 0x00, 0x00, 0x2f, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
- 0x30, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x28, 0x01, 0x00, 0x00,
- 0x31, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x32, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0xbe, 0x00, 0x05, 0x00,
- 0x7d, 0x00, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00,
- 0x7c, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x35, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x33, 0x01, 0x00, 0x00,
- 0x34, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x34, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x37, 0x01, 0x00, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x7f, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
- 0x28, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x3a, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x39, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x3b, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
- 0x3a, 0x01, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x3c, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3d, 0x01, 0x00, 0x00,
- 0x16, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x3e, 0x01, 0x00, 0x00, 0x1b, 0x01, 0x00, 0x00, 0x3d, 0x01, 0x00, 0x00,
- 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00,
- 0x3c, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x36, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00,
- 0x11, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x43, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x8e, 0x00, 0x05, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00,
- 0x43, 0x01, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x45, 0x01, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x40, 0x01, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00,
- 0x40, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x47, 0x01, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x43, 0x00, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x4a, 0x01, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00,
- 0xf9, 0x00, 0x02, 0x00, 0x35, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x35, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x4c, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x4d, 0x01, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4e, 0x01, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00,
- 0x4d, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x4f, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x4e, 0x01, 0x00, 0x00,
- 0x4f, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x51, 0x01, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00,
- 0x51, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x4b, 0x01, 0x00, 0x00,
- 0x52, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00,
- 0x53, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x54, 0x01, 0x00, 0x00, 0x53, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x5d, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00,
- 0x41, 0x00, 0x06, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00,
- 0x57, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xc2, 0x00, 0x00, 0x00,
- 0x59, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x5a, 0x01, 0x00, 0x00, 0x59, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x5b, 0x01, 0x00, 0x00, 0x4b, 0x01, 0x00, 0x00,
- 0x0c, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00,
- 0x5a, 0x01, 0x00, 0x00, 0x5b, 0x01, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x5d, 0x01, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00,
- 0x5c, 0x01, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00,
- 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00,
- 0x56, 0x01, 0x00, 0x00, 0x5d, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x5f, 0x01, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0x60, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x60, 0x01, 0x00, 0x00,
- 0xf6, 0x00, 0x04, 0x00, 0x62, 0x01, 0x00, 0x00, 0x63, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x64, 0x01, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x64, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00,
- 0x7c, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00,
- 0x65, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xd5, 0x00, 0x00, 0x00,
- 0x67, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00,
- 0x67, 0x01, 0x00, 0x00, 0xb0, 0x00, 0x05, 0x00, 0x7d, 0x00, 0x00, 0x00,
- 0x69, 0x01, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00,
- 0xfa, 0x00, 0x04, 0x00, 0x69, 0x01, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
- 0x62, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x61, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x6b, 0x01, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x5d, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x6b, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x6d, 0x01, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x6e, 0x01, 0x00, 0x00,
- 0x5f, 0x01, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x6f, 0x01, 0x00, 0x00, 0x6e, 0x01, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x06, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x6f, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x71, 0x01, 0x00, 0x00,
- 0x70, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x72, 0x01, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0xc2, 0x00, 0x00, 0x00, 0x73, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x72, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x73, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x75, 0x01, 0x00, 0x00,
- 0x4b, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x76, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
- 0x71, 0x01, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x75, 0x01, 0x00, 0x00,
- 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x77, 0x01, 0x00, 0x00,
- 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00,
- 0x76, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x78, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
- 0x6a, 0x01, 0x00, 0x00, 0x6d, 0x01, 0x00, 0x00, 0x77, 0x01, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00,
- 0xf9, 0x00, 0x02, 0x00, 0x63, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x63, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x79, 0x01, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5f, 0x01, 0x00, 0x00,
- 0x7a, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x60, 0x01, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x62, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
- 0x7f, 0x01, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x81, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
- 0xbe, 0x00, 0x05, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00,
- 0x81, 0x01, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00,
- 0x84, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
- 0x82, 0x01, 0x00, 0x00, 0x83, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x83, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x86, 0x01, 0x00, 0x00, 0x89, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x7d, 0x01, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x00,
- 0x7f, 0x01, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x8b, 0x01, 0x00, 0x00, 0x89, 0x01, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x00,
- 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00,
- 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x8e, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x00, 0x00,
- 0x8d, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0x84, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x84, 0x01, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
- 0x8f, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x91, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x05, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x92, 0x01, 0x00, 0x00, 0x91, 0x01, 0x00, 0x00,
- 0x90, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x92, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x95, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x94, 0x01, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
- 0x38, 0x00, 0x01, 0x00
-};
-unsigned int vkvg_main_frag_spv_len = 9532;
-unsigned char vkvg_main_vert_spv[] = {
- 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00,
- 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
- 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x27, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x42, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00,
- 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73,
- 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x64,
- 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00,
- 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73,
- 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75,
- 0x61, 0x67, 0x65, 0x5f, 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6b, 0x00,
- 0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c,
- 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f,
- 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
- 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47,
- 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64,
- 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x6f, 0x75, 0x74, 0x50, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00,
- 0x05, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x50, 0x75, 0x73, 0x68,
- 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x73, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x66, 0x75, 0x6c, 0x6c, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x51, 0x75,
- 0x61, 0x64, 0x5f, 0x73, 0x72, 0x63, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00,
- 0x06, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x00, 0x06, 0x00, 0x04, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x74, 0x00,
- 0x06, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x6d, 0x61, 0x74, 0x49, 0x6e, 0x76, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0x70, 0x63, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x4d, 0x61, 0x74, 0x00, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x53,
- 0x72, 0x63, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00,
- 0x69, 0x6e, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x05, 0x00, 0x05, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x4f, 0x70, 0x61, 0x63, 0x69,
- 0x74, 0x79, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x67, 0x6c, 0x5f, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78,
- 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x06, 0x00, 0x07, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74,
- 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00,
- 0x3e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43,
- 0x6c, 0x69, 0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00,
- 0x06, 0x00, 0x07, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x67, 0x6c, 0x5f, 0x43, 0x75, 0x6c, 0x6c, 0x44, 0x69, 0x73, 0x74, 0x61,
- 0x6e, 0x63, 0x65, 0x00, 0x05, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x42, 0x00, 0x00, 0x00,
- 0x69, 0x6e, 0x50, 0x6f, 0x73, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x55, 0x56, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x51, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x55, 0x56,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x70, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
- 0x3e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
- 0x3e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x42, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x51, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x19, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x14, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00,
- 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x2a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2e, 0x00, 0x00, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x31, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x15, 0x00, 0x04, 0x00,
- 0x3b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x3d, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00,
- 0x3e, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x3f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x41, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x17, 0x00, 0x04, 0x00,
- 0x4a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x4a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x4b, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf,
- 0x2c, 0x00, 0x06, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00,
- 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x4a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x50, 0x00, 0x00, 0x00,
- 0x51, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x53, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x3b, 0x00, 0x00, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x59, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2c, 0x00, 0x05, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
- 0x77, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x7a, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x05, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
- 0x45, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00,
- 0x12, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
- 0x12, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
- 0xf7, 0x00, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfa, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x29, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x27, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x29, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
- 0x1f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0x25, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x2d, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x31, 0x00, 0x00, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x2f, 0x00, 0x00, 0x00,
- 0x33, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
- 0xaa, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00,
- 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
- 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
- 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00,
- 0x44, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x1f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x49, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x4e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x3a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00,
- 0x52, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
- 0x55, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x57, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x59, 0x00, 0x00, 0x00,
- 0x5a, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
- 0x5a, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x5f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x59, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
- 0x3c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x61, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00,
- 0x61, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x63, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x65, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00,
- 0x65, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00, 0x00,
- 0x67, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00,
- 0x1f, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x59, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
- 0x42, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00,
- 0x68, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
- 0x55, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x59, 0x00, 0x00, 0x00,
- 0x6e, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
- 0x6e, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x70, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
- 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
- 0x6b, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
- 0x55, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x74, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00,
- 0x66, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x54, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00,
- 0x76, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x7a, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
- 0x5d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x7c, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00,
- 0x7c, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
- 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x82, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00,
- 0x44, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x1f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x83, 0x00, 0x00, 0x00,
- 0x82, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2e, 0x00, 0x00, 0x00,
- 0x84, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x84, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
- 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
-};
-unsigned int vkvg_main_vert_spv_len = 3704;
+ 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
+ 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+ 0x00, 0x21, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x10, 0x00,
+ 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2,
+ 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72,
+ 0x61, 0x74, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x00,
+ 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67,
+ 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6b, 0x00, 0x04,
+ 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x45, 0x58, 0x54, 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x61, 0x72, 0x5f, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x5f, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f,
+ 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69,
+ 0x6e, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47,
+ 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x53, 0x72, 0x63, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x0f,
+ 0x00, 0x00, 0x00, 0x69, 0x6e, 0x50, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
+ 0x17, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f,
+ 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x1e, 0x00,
+ 0x00, 0x00, 0x75, 0x76, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x4d, 0x61, 0x74,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00, 0x00,
+ 0x05, 0x00, 0x04, 0x00, 0x52, 0x00, 0x00, 0x00, 0x64, 0x69, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03,
+ 0x00, 0x54, 0x00, 0x00, 0x00, 0x70, 0x30, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5f, 0x75,
+ 0x62, 0x6f, 0x47, 0x72, 0x61, 0x64, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x73, 0x74, 0x6f, 0x70, 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x5a, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x63, 0x70, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x75,
+ 0x62, 0x6f, 0x47, 0x72, 0x61, 0x64, 0x00, 0x05, 0x00, 0x03, 0x00, 0x64, 0x00, 0x00, 0x00, 0x70, 0x31, 0x00, 0x00,
+ 0x05, 0x00, 0x03, 0x00, 0x70, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x75, 0x00, 0x00,
+ 0x00, 0x75, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x97, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x03, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x62, 0x62, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x69,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xf2, 0x00, 0x00, 0x00, 0x63, 0x30, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
+ 0xf9, 0x00, 0x00, 0x00, 0x63, 0x31, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x72, 0x30, 0x00,
+ 0x00, 0x05, 0x00, 0x03, 0x00, 0x06, 0x01, 0x00, 0x00, 0x72, 0x31, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x0c, 0x01,
+ 0x00, 0x00, 0x67, 0x72, 0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0d,
+ 0x01, 0x00, 0x00, 0x64, 0x69, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x11, 0x01, 0x00, 0x00,
+ 0x72, 0x61, 0x79, 0x44, 0x69, 0x72, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x16, 0x01, 0x00, 0x00, 0x61, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x03, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x20, 0x01,
+ 0x00, 0x00, 0x63, 0x63, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x28, 0x01, 0x00, 0x00, 0x64, 0x69, 0x73, 0x63, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x36, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
+ 0x40, 0x01, 0x00, 0x00, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x05, 0x00, 0x04,
+ 0x00, 0x4b, 0x01, 0x00, 0x00, 0x67, 0x72, 0x61, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x5f, 0x01,
+ 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x69, 0x6e, 0x46, 0x6f, 0x6e,
+ 0x74, 0x55, 0x56, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x88, 0x01, 0x00, 0x00, 0x66, 0x6f, 0x6e, 0x74,
+ 0x4d, 0x61, 0x70, 0x00, 0x05, 0x00, 0x05, 0x00, 0x8f, 0x01, 0x00, 0x00, 0x69, 0x6e, 0x4f, 0x70, 0x61, 0x63, 0x69,
+ 0x74, 0x79, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x94, 0x01, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x46, 0x72, 0x61,
+ 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x96, 0x01, 0x00, 0x00, 0x4e,
+ 0x55, 0x4d, 0x5f, 0x53, 0x41, 0x4d, 0x50, 0x4c, 0x45, 0x53, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
+ 0x00, 0x47, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00,
+ 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x21,
+ 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00,
+ 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47,
+ 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+ 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05,
+ 0x00, 0x5a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x48, 0x00,
+ 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x48,
+ 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
+ 0x47, 0x00, 0x03, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x00,
+ 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x21, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x88, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x47, 0x00, 0x04, 0x00, 0x88, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03,
+ 0x00, 0x8f, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x8f, 0x01, 0x00, 0x00, 0x1e, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x94, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x96, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x15, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0e,
+ 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x15, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00,
+ 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04,
+ 0x00, 0x0d, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x23, 0x00,
+ 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x34,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x47, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x48, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x04, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x49,
+ 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x2b, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x55, 0x00,
+ 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x2b,
+ 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
+ 0x59, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, 0x5a, 0x00, 0x00,
+ 0x00, 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x04, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x5d, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xc2, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xd5, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00,
+ 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2b, 0x00,
+ 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x17, 0x00, 0x04, 0x00, 0x7d,
+ 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x7e, 0x01, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x7d, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x7e, 0x01, 0x00, 0x00, 0x7f, 0x01, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x85, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x86, 0x01, 0x00, 0x00, 0x85, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+ 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x87, 0x01, 0x00,
+ 0x00, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x8f, 0x01,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x93, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x93, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x32, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x96, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00,
+ 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00,
+ 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x64,
+ 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00,
+ 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xcb,
+ 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0xf2, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00,
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b,
+ 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+ 0x16, 0x00, 0x00, 0x00, 0x0d, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00,
+ 0x00, 0x11, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x16, 0x01,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00,
+ 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x4b,
+ 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
+ 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00,
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xfb, 0x00, 0x09, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00,
+ 0x00, 0xf8, 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x19, 0x00,
+ 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x19,
+ 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00,
+ 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1c,
+ 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
+ 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
+ 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x41, 0x00,
+ 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d,
+ 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06,
+ 0x00, 0x25, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x41,
+ 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x81, 0x00,
+ 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x41,
+ 0x00, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00,
+ 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x36, 0x00,
+ 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22,
+ 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00,
+ 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3a, 0x00,
+ 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3b,
+ 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00,
+ 0x00, 0x3d, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x17, 0x00,
+ 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3f,
+ 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00,
+ 0x00, 0x41, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x21, 0x00,
+ 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44,
+ 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
+ 0x42, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00,
+ 0x00, 0x37, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x46, 0x00,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x48, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3d,
+ 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00,
+ 0x00, 0x4e, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4e,
+ 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
+ 0x4f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02,
+ 0x00, 0x14, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x52, 0x00,
+ 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x5c,
+ 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x5f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x5f, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15,
+ 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x62, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x41, 0x00,
+ 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x22,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x68, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x68,
+ 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
+ 0x15, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03,
+ 0x00, 0x64, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6b, 0x00,
+ 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6b,
+ 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00,
+ 0x00, 0x6e, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6e,
+ 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x15, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00,
+ 0x00, 0x72, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x73, 0x00,
+ 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00,
+ 0x00, 0x64, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x54, 0x00,
+ 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x45, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x75, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00,
+ 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x2f, 0x00,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0xb4,
+ 0x00, 0x05, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0xf7, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x7e, 0x00, 0x00,
+ 0x00, 0x7f, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x41, 0x00,
+ 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d,
+ 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00,
+ 0x7d, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03,
+ 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x83, 0x00, 0x00, 0x00, 0x84, 0x00,
+ 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x84, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28,
+ 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00,
+ 0x00, 0x88, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8a,
+ 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x8b, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00,
+ 0x00, 0x70, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x8b, 0x00,
+ 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x52, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0xf9,
+ 0x00, 0x02, 0x00, 0x85, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00,
+ 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x93, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x94, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x95, 0x00,
+ 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x52, 0x00, 0x00, 0x00, 0x95,
+ 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x85, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x85, 0x00, 0x00, 0x00,
+ 0xf9, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x96, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x04, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x9b, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x9c, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9d, 0x00,
+ 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x97, 0x00, 0x00, 0x00, 0x9d,
+ 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00,
+ 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x41, 0x00,
+ 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d,
+ 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x3e, 0x00,
+ 0x03, 0x00, 0x9e, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0xa6,
+ 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xa7, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00,
+ 0x00, 0x97, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x17, 0x00,
+ 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xa9,
+ 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,
+ 0xaa, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00,
+ 0x00, 0xab, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x9e, 0x00,
+ 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0xad,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x81, 0x00,
+ 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x0c,
+ 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+ 0xb2, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00,
+ 0x00, 0xb3, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0x70, 0x00,
+ 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb5,
+ 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x52, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, 0x7d, 0x00,
+ 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xbb,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xb9, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00,
+ 0xbb, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xba, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0xbc, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xbd, 0x00,
+ 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x52, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0xf9,
+ 0x00, 0x02, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00,
+ 0x00, 0xbe, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5d,
+ 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06,
+ 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x22, 0x00,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0x41,
+ 0x00, 0x06, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00,
+ 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xc4,
+ 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0xc9, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00,
+ 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00,
+ 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09,
+ 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0xf9, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04,
+ 0x00, 0xcf, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xd1, 0x00,
+ 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xd2,
+ 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00,
+ 0xd2, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xd5, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
+ 0x00, 0xd4, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0xd6, 0x00,
+ 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x2f,
+ 0x00, 0x00, 0x00, 0xb0, 0x00, 0x05, 0x00, 0x7d, 0x00, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00,
+ 0xd8, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xd9, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00,
+ 0x00, 0xf8, 0x00, 0x02, 0x00, 0xce, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xda, 0x00,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, 0xcc,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
+ 0x00, 0x22, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xde, 0x00,
+ 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0xcc,
+ 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00,
+ 0x00, 0xe0, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0xcc, 0x00,
+ 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x2c,
+ 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00,
+ 0x00, 0xe4, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x52, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31,
+ 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00,
+ 0x00, 0xe7, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x3e,
+ 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xd0, 0x00, 0x00, 0x00,
+ 0xf8, 0x00, 0x02, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0xea, 0x00,
+ 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0xf9,
+ 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xcf, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0xed, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0xee, 0x00,
+ 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3d,
+ 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
+ 0x15, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0xee, 0x00,
+ 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x41,
+ 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x22, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00,
+ 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xf4, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xf6,
+ 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00,
+ 0xf6, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05,
+ 0x00, 0x15, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x3e, 0x00,
+ 0x03, 0x00, 0xf2, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0xfa,
+ 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00,
+ 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x4f,
+ 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x34,
+ 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00,
+ 0x00, 0x0b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x01,
+ 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x02,
+ 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00,
+ 0x41, 0x00, 0x07, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00,
+ 0x00, 0x2c, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x01,
+ 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x0b,
+ 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00,
+ 0x09, 0x01, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00,
+ 0x00, 0x0a, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x06, 0x01, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x3e, 0x00,
+ 0x03, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x0e,
+ 0x01, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x00,
+ 0xf9, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00,
+ 0x00, 0x0f, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x0d, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15,
+ 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00,
+ 0x14, 0x01, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
+ 0x00, 0x15, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x3e, 0x00,
+ 0x03, 0x00, 0x11, 0x01, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x17,
+ 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00,
+ 0x11, 0x01, 0x00, 0x00, 0x94, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x17, 0x01, 0x00,
+ 0x00, 0x18, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x16, 0x01, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15,
+ 0x00, 0x00, 0x00, 0x1d, 0x01, 0x00, 0x00, 0x0d, 0x01, 0x00, 0x00, 0x94, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x1e, 0x01, 0x00, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x1d, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x1f, 0x01, 0x00, 0x00, 0x1b, 0x01, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x1a, 0x01,
+ 0x00, 0x00, 0x1f, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x0d,
+ 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, 0x0d, 0x01, 0x00, 0x00,
+ 0x94, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x22, 0x01, 0x00,
+ 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03,
+ 0x00, 0x20, 0x01, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x29, 0x01,
+ 0x00, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2a, 0x01, 0x00, 0x00, 0x1a,
+ 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00,
+ 0x2a, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00, 0x16, 0x01, 0x00,
+ 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2e, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x2d, 0x01,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2f, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x85,
+ 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x2e, 0x01, 0x00, 0x00, 0x2f, 0x01, 0x00, 0x00,
+ 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00, 0x30, 0x01, 0x00,
+ 0x00, 0x3e, 0x00, 0x03, 0x00, 0x28, 0x01, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0xbe, 0x00, 0x05, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x33,
+ 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x35, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x33, 0x01, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00,
+ 0x00, 0xf8, 0x00, 0x02, 0x00, 0x34, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x01,
+ 0x00, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x7f, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x37,
+ 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
+ 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3a, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x39, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3a, 0x01, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3c,
+ 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x3d, 0x01, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3e, 0x01, 0x00,
+ 0x00, 0x1b, 0x01, 0x00, 0x00, 0x3d, 0x01, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3f, 0x01,
+ 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x36, 0x01, 0x00, 0x00, 0x3f,
+ 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x8e, 0x00, 0x05, 0x00, 0x15, 0x00,
+ 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x15,
+ 0x00, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+ 0x40, 0x01, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x46, 0x01, 0x00,
+ 0x00, 0x40, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0xf2, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x43,
+ 0x00, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x49, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4a, 0x01, 0x00,
+ 0x00, 0x48, 0x01, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x4a, 0x01,
+ 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x35, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x35, 0x01, 0x00, 0x00, 0x3d,
+ 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x15, 0x00, 0x00, 0x00, 0x4d, 0x01, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x4e, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x4d, 0x01,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x83,
+ 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x4e, 0x01, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x88, 0x00, 0x05,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, 0x3e, 0x00,
+ 0x03, 0x00, 0x4b, 0x01, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x53,
+ 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x53, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00,
+ 0x00, 0x55, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xc2,
+ 0x00, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06,
+ 0x00, 0xc2, 0x00, 0x00, 0x00, 0x59, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2c, 0x00,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5a, 0x01, 0x00, 0x00, 0x59, 0x01, 0x00, 0x00, 0x3d,
+ 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5b, 0x01, 0x00, 0x00, 0x4b, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00,
+ 0x00, 0x5a, 0x01, 0x00, 0x00, 0x5b, 0x01, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5d, 0x01,
+ 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x0c,
+ 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
+ 0x54, 0x01, 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x5d, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00,
+ 0x00, 0x5e, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xf9, 0x00,
+ 0x02, 0x00, 0x60, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x60, 0x01, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x62,
+ 0x01, 0x00, 0x00, 0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x64, 0x01, 0x00, 0x00,
+ 0xf8, 0x00, 0x02, 0x00, 0x64, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x65, 0x01, 0x00,
+ 0x00, 0x5f, 0x01, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00, 0x65, 0x01,
+ 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xd5, 0x00, 0x00, 0x00, 0x67, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xd4,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x67, 0x01, 0x00, 0x00,
+ 0xb0, 0x00, 0x05, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x69, 0x01, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00, 0x68, 0x01, 0x00,
+ 0x00, 0xfa, 0x00, 0x04, 0x00, 0x69, 0x01, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00, 0x62, 0x01, 0x00, 0x00, 0xf8, 0x00,
+ 0x02, 0x00, 0x61, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x00, 0x00, 0x09,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x6b, 0x01, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00,
+ 0x41, 0x00, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
+ 0x00, 0x6b, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6d, 0x01, 0x00, 0x00, 0x6c, 0x01,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x6e, 0x01, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x82,
+ 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x6f, 0x01, 0x00, 0x00, 0x6e, 0x01, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x41, 0x00, 0x06, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00,
+ 0x00, 0x6f, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x71, 0x01, 0x00, 0x00, 0x70, 0x01,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x72, 0x01, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x41,
+ 0x00, 0x06, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x73, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x72, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x73, 0x01, 0x00,
+ 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x75, 0x01, 0x00, 0x00, 0x4b, 0x01, 0x00, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x71,
+ 0x01, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x75, 0x01, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x77, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00,
+ 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00,
+ 0x00, 0x00, 0x6a, 0x01, 0x00, 0x00, 0x6d, 0x01, 0x00, 0x00, 0x77, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09,
+ 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x63, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
+ 0x63, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x5f, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x2c, 0x00,
+ 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x7a, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x60,
+ 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x62, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0xf8, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00,
+ 0x00, 0x7f, 0x01, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x81, 0x01,
+ 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xbe, 0x00, 0x05, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, 0x81,
+ 0x01, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x84, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfa, 0x00, 0x04, 0x00, 0x82, 0x01, 0x00, 0x00, 0x83, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02,
+ 0x00, 0x83, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x86, 0x01, 0x00, 0x00, 0x89, 0x01, 0x00, 0x00, 0x88, 0x01,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x7d, 0x01, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x57,
+ 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8b, 0x01, 0x00, 0x00, 0x89, 0x01, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x00,
+ 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8e, 0x00,
+ 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x3e,
+ 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x84, 0x01, 0x00, 0x00,
+ 0xf8, 0x00, 0x02, 0x00, 0x84, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00,
+ 0x00, 0x8f, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x91, 0x01, 0x00, 0x00, 0x09, 0x00,
+ 0x00, 0x00, 0x8e, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x92, 0x01, 0x00, 0x00, 0x91, 0x01, 0x00, 0x00, 0x90,
+ 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x92, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x94, 0x01, 0x00,
+ 0x00, 0x95, 0x01, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
+unsigned int vkvg_main_frag_spv_len = 9532;
+unsigned char vkvg_main_vert_spv[] = {
+ 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
+ 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00,
+ 0x00, 0x27, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x4c, 0x00,
+ 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x04,
+ 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f,
+ 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x09,
+ 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x61, 0x6e,
+ 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6b, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47,
+ 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f,
+ 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08,
+ 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f,
+ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d,
+ 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x50,
+ 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x50, 0x75, 0x73,
+ 0x68, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x73, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x66, 0x75, 0x6c, 0x6c, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x51, 0x75, 0x61, 0x64, 0x5f,
+ 0x73, 0x72, 0x63, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x00, 0x06, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x6d, 0x61, 0x74, 0x00, 0x06, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x74, 0x49, 0x6e, 0x76, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x70, 0x63, 0x00,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x4d, 0x61, 0x74, 0x00, 0x00, 0x05, 0x00,
+ 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x53, 0x72, 0x63, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x27,
+ 0x00, 0x00, 0x00, 0x69, 0x6e, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x05, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x00, 0x00,
+ 0x6f, 0x75, 0x74, 0x4f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x3e, 0x00, 0x00,
+ 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x06, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x00, 0x06, 0x00, 0x07, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50,
+ 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x3e, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43, 0x6c, 0x69, 0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63,
+ 0x65, 0x00, 0x06, 0x00, 0x07, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43, 0x75,
+ 0x6c, 0x6c, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x05, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x42, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x50, 0x6f, 0x73, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x55, 0x56, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x04, 0x00, 0x51, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x55, 0x56, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x54,
+ 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x47, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05,
+ 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00,
+ 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48,
+ 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,
+ 0x00, 0x48, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x00,
+ 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x48,
+ 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05,
+ 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48, 0x00,
+ 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x47,
+ 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2f,
+ 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e,
+ 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
+ 0x3e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x42, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x51, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00,
+ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x17, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04,
+ 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x08, 0x00, 0x0d, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c,
+ 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x0d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
+ 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x26,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00,
+ 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
+ 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00,
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b,
+ 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+ 0x31, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x15, 0x00, 0x04, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x1e, 0x00, 0x06, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00,
+ 0x00, 0x3d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3e, 0x00,
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x04, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+ 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00,
+ 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x45, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x17, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
+ 0x3b, 0x00, 0x04, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04,
+ 0x00, 0x09, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf, 0x2c, 0x00, 0x06, 0x00, 0x4a, 0x00,
+ 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x04, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+ 0x50, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x53, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04,
+ 0x00, 0x09, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2c, 0x00, 0x05, 0x00, 0x0b, 0x00,
+ 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x7a,
+ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x7e, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00,
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b,
+ 0x00, 0x04, 0x00, 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
+ 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00,
+ 0x00, 0x1a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x05, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00,
+ 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
+ 0x00, 0x29, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0a, 0x00,
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x28,
+ 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x25, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x29, 0x00, 0x00, 0x00,
+ 0x41, 0x00, 0x05, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00,
+ 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3e, 0x00,
+ 0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x25, 0x00, 0x00, 0x00, 0xf8,
+ 0x00, 0x02, 0x00, 0x25, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
+ 0x23, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05,
+ 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x2f,
+ 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00,
+ 0x00, 0x34, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x35, 0x00,
+ 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x37,
+ 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfa, 0x00, 0x04, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02,
+ 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x42, 0x00,
+ 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00,
+ 0x00, 0x47, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1c, 0x00,
+ 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x49,
+ 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00,
+ 0xfd, 0x00, 0x01, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00,
+ 0x00, 0x52, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x52, 0x00,
+ 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x55,
+ 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x59, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00,
+ 0x00, 0x42, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x58,
+ 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04,
+ 0x00, 0x09, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x59, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09,
+ 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x62, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00,
+ 0x00, 0x63, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x31, 0x00,
+ 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x56,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00,
+ 0x00, 0x41, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x55, 0x00,
+ 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x68,
+ 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x59, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
+ 0x42, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00,
+ 0x00, 0x69, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x68, 0x00,
+ 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0f,
+ 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x59, 0x00, 0x00,
+ 0x00, 0x6e, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00,
+ 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x70,
+ 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x71, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00,
+ 0x00, 0x72, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x81,
+ 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
+ 0x50, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00,
+ 0x00, 0x3e, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00,
+ 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x79,
+ 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x7a, 0x00, 0x00, 0x00,
+ 0x7b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00,
+ 0x00, 0x7c, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x7d, 0x00,
+ 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x7f,
+ 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00,
+ 0x00, 0x81, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x0a, 0x00,
+ 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x45,
+ 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x1f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x83, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05,
+ 0x00, 0x2e, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x3e, 0x00,
+ 0x03, 0x00, 0x84, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
+unsigned int vkvg_main_vert_spv_len = 3704;
unsigned char vkvg_main_lcd_frag_spv[] = {
- 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00,
- 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
- 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x25, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00,
- 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73,
- 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x64,
- 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00,
- 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73,
- 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75,
- 0x61, 0x67, 0x65, 0x5f, 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6b, 0x00,
- 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x45, 0x58, 0x54, 0x5f, 0x73,
- 0x63, 0x61, 0x6c, 0x61, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
- 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00,
- 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70,
- 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65,
- 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00,
- 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c,
- 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69,
- 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x05, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x50, 0x61,
- 0x74, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x53, 0x72, 0x63, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x06, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x46,
- 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x22, 0x00, 0x00, 0x00, 0x75, 0x76, 0x00, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x4d, 0x61,
- 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x4e, 0x00, 0x00, 0x00,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5f, 0x75, 0x62, 0x6f,
- 0x47, 0x72, 0x61, 0x64, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f,
- 0x72, 0x73, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x73, 0x74, 0x6f, 0x70, 0x73, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x63, 0x70, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x75, 0x62, 0x6f, 0x47,
- 0x72, 0x61, 0x64, 0x00, 0x05, 0x00, 0x09, 0x00, 0x6c, 0x00, 0x00, 0x00,
- 0x67, 0x72, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x72,
- 0x74, 0x50, 0x6f, 0x73, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x58,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x78, 0x00, 0x00, 0x00,
- 0x67, 0x72, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x64, 0x50,
- 0x6f, 0x73, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x58, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x84, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x88, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x03, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x05, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x78, 0x4c, 0x6f, 0x63,
- 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x00, 0x05, 0x00, 0x03, 0x00,
- 0xae, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
- 0xdc, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x46, 0x6f, 0x6e, 0x74, 0x55, 0x56,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xe5, 0x00, 0x00, 0x00,
- 0x66, 0x6f, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x00, 0x05, 0x00, 0x06, 0x00,
- 0xec, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x46, 0x72, 0x61, 0x67, 0x43,
- 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
- 0xee, 0x00, 0x00, 0x00, 0x4e, 0x55, 0x4d, 0x5f, 0x53, 0x41, 0x4d, 0x50,
- 0x4c, 0x45, 0x53, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x4e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x59, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00,
- 0x47, 0x00, 0x03, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5e, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0xdc, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xe5, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0xec, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0xee, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
- 0x4b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00,
- 0x57, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
- 0x58, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x57, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00,
- 0x5a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
- 0x5b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x06, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x59, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x5c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x5d, 0x00, 0x00, 0x00,
- 0x5e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x5f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x98, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xad, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x27, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0xbb, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x04, 0x00, 0xda, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xdb, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0xdb, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x19, 0x00, 0x09, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x1b, 0x00, 0x03, 0x00, 0xe3, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe3, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xe4, 0x00, 0x00, 0x00,
- 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0xeb, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0xeb, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x32, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0xee, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0x1b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x1a, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x88, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xad, 0x00, 0x00, 0x00,
- 0xae, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0xf7, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfb, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0x4f, 0x00, 0x07, 0x00, 0x19, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
- 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
- 0x2a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x2d, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
- 0x2d, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
- 0x25, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x36, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
- 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
- 0x2f, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x29, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
- 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x29, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0x26, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x1b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x29, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
- 0x1b, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
- 0x42, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x45, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x4a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x22, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
- 0x4e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0x4f, 0x00, 0x07, 0x00, 0x19, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
- 0x51, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x53, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
- 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x4f, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x12, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x07, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
- 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x61, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x07, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00,
- 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
- 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x5f, 0x00, 0x00, 0x00,
- 0x66, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x07, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
- 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x69, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00,
- 0x69, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x6b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x65, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00,
- 0x5f, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00,
- 0x6d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x6f, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00,
- 0x70, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x5f, 0x00, 0x00, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x26, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x74, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x76, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00,
- 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
- 0x71, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00,
- 0x5f, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00,
- 0x79, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x7b, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00,
- 0x7c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x5f, 0x00, 0x00, 0x00,
- 0x7e, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x81, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x82, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00,
- 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00,
- 0x7d, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x78, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x87, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x84, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x88, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00,
- 0x8b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x90, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00,
- 0x91, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x93, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
- 0x93, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00,
- 0x96, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x8e, 0x00, 0x00, 0x00,
- 0x97, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x98, 0x00, 0x00, 0x00,
- 0x99, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
- 0x26, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x9a, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x98, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
- 0x26, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5f, 0x00, 0x00, 0x00,
- 0x9e, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x26, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x9f, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00,
- 0x9f, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00,
- 0xa1, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xa3, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
- 0x5f, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00,
- 0x84, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xa7, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00,
- 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,
- 0xa3, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00,
- 0xa8, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
- 0xaa, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00,
- 0x9c, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0xae, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0xaf, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xaf, 0x00, 0x00, 0x00,
- 0xf6, 0x00, 0x04, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xb3, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00,
- 0x7c, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00,
- 0xb4, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xb7, 0x00, 0x00, 0x00,
- 0xb8, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00,
- 0xb8, 0x00, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00,
- 0xba, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
- 0xb0, 0x00, 0x05, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00,
- 0xb5, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
- 0xbc, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
- 0xae, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0xbf, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x06, 0x00, 0x98, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
- 0x5e, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
- 0xc0, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xc2, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00,
- 0x41, 0x00, 0x06, 0x00, 0x5f, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00,
- 0x5e, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00,
- 0xc4, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xc6, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00,
- 0xc6, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xc8, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0xca, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5f, 0x00, 0x00, 0x00,
- 0xcc, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0xcb, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xcd, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00,
- 0xcd, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
- 0xcf, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xd1, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00,
- 0xd1, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0xd3, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00,
- 0xd2, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x2e, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
- 0xd3, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0xd4, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xb2, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00,
- 0xd5, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0xae, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0xaf, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb1, 0x00, 0x00, 0x00,
- 0xf9, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0x13, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
- 0x29, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00,
- 0x5a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xde, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x05, 0x00,
- 0xbb, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xe1, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xdf, 0x00, 0x00, 0x00,
- 0xe0, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
- 0xe0, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0xe3, 0x00, 0x00, 0x00,
- 0xe6, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0xda, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00,
- 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00,
- 0xe6, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x85, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00,
- 0xe9, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
- 0xe1, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xe1, 0x00, 0x00, 0x00,
- 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xec, 0x00, 0x00, 0x00,
- 0xed, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
-};
-unsigned int vkvg_main_lcd_frag_spv_len = 5784;
-unsigned char wired_frag_spv[] = {
- 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
- 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00,
- 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73,
- 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x64,
- 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00,
- 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73,
- 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75,
- 0x61, 0x67, 0x65, 0x5f, 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6b, 0x00,
- 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x45, 0x58, 0x54, 0x5f, 0x73,
- 0x63, 0x61, 0x6c, 0x61, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
- 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00,
- 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70,
- 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65,
- 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00,
- 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c,
- 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69,
- 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x46,
- 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x66, 0x6f, 0x6e, 0x74,
- 0x4d, 0x61, 0x70, 0x00, 0x05, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
- 0x1a, 0x00, 0x00, 0x00, 0x5f, 0x75, 0x62, 0x6f, 0x47, 0x72, 0x61, 0x64,
- 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x00, 0x00,
- 0x06, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x73, 0x74, 0x6f, 0x70, 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00,
- 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x63, 0x70, 0x00, 0x00,
- 0x06, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x75, 0x62, 0x6f, 0x47, 0x72, 0x61, 0x64, 0x00,
- 0x05, 0x00, 0x05, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x46, 0x6f,
- 0x6e, 0x74, 0x55, 0x56, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x53, 0x72, 0x63, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x05, 0x00, 0x24, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x50, 0x61,
- 0x74, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
- 0x26, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x4f, 0x70, 0x61, 0x63, 0x69, 0x74,
- 0x79, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00,
- 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x4e, 0x55, 0x4d, 0x5f, 0x53, 0x41, 0x4d, 0x50,
- 0x4c, 0x45, 0x53, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00,
- 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x19, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
- 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00,
- 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
- 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x21, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x03, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x26, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x2a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0x3f, 0x2c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
- 0x19, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x06, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x1a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
- 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x17, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x27, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00,
- 0x2b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
- 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
-};
+ 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
+ 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,
+ 0x00, 0x25, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x04,
+ 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f,
+ 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x09,
+ 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x61, 0x6e,
+ 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47,
+ 0x4c, 0x5f, 0x45, 0x58, 0x54, 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x61, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
+ 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47,
+ 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f,
+ 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x0e, 0x00,
+ 0x00, 0x00, 0x69, 0x6e, 0x50, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x16,
+ 0x00, 0x00, 0x00, 0x69, 0x6e, 0x53, 0x72, 0x63, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x1b, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67,
+ 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x22, 0x00, 0x00, 0x00, 0x75, 0x76,
+ 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x00, 0x00, 0x00, 0x05,
+ 0x00, 0x04, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
+ 0x56, 0x00, 0x00, 0x00, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00,
+ 0x00, 0x5f, 0x75, 0x62, 0x6f, 0x47, 0x72, 0x61, 0x64, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x5c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x5c,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x74, 0x6f, 0x70, 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00,
+ 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x63, 0x70, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x5e, 0x00,
+ 0x00, 0x00, 0x75, 0x62, 0x6f, 0x47, 0x72, 0x61, 0x64, 0x00, 0x05, 0x00, 0x09, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x67,
+ 0x72, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x6f, 0x73, 0x52, 0x6f, 0x74, 0x61,
+ 0x74, 0x65, 0x64, 0x58, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x78, 0x00, 0x00, 0x00, 0x67, 0x72, 0x61,
+ 0x64, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x64, 0x50, 0x6f, 0x73, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x58,
+ 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x84, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x88,
+ 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x05, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x78, 0x4c, 0x6f, 0x63, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64,
+ 0x00, 0x05, 0x00, 0x03, 0x00, 0xae, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0xdc, 0x00,
+ 0x00, 0x00, 0x69, 0x6e, 0x46, 0x6f, 0x6e, 0x74, 0x55, 0x56, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xe5,
+ 0x00, 0x00, 0x00, 0x66, 0x6f, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x00, 0x05, 0x00, 0x06, 0x00, 0xec, 0x00, 0x00, 0x00,
+ 0x6f, 0x75, 0x74, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05,
+ 0x00, 0xee, 0x00, 0x00, 0x00, 0x4e, 0x55, 0x4d, 0x5f, 0x53, 0x41, 0x4d, 0x50, 0x4c, 0x45, 0x53, 0x00, 0x47, 0x00,
+ 0x03, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1e,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
+ 0x00, 0x47, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00,
+ 0x04, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4e,
+ 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00,
+ 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47,
+ 0x00, 0x04, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+ 0x5e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xdc, 0x00, 0x00,
+ 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x22, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xec, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x47, 0x00, 0x04, 0x00, 0xee, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00,
+ 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x2c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00,
+ 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x19,
+ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x3b,
+ 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04,
+ 0x00, 0x27, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00,
+ 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x04, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x3b, 0x00,
+ 0x04, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x27,
+ 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x57, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x1e,
+ 0x00, 0x06, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
+ 0x27, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
+ 0x00, 0x3b, 0x00, 0x04, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x98,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xad, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x27, 0x00,
+ 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0xda, 0x00, 0x00, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xdb, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xda, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xdb, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x19, 0x00, 0x09, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x00, 0x03, 0x00, 0xe3, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xe4, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xe4, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00,
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xeb, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x32,
+ 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02,
+ 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x07, 0x00,
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b,
+ 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00,
+ 0x00, 0x6c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x78, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04,
+ 0x00, 0x2c, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xad, 0x00,
+ 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0xf7, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00,
+ 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf8,
+ 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+ 0x16, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02,
+ 0x00, 0x14, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00,
+ 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1e,
+ 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07,
+ 0x00, 0x19, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x1e,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+ 0x41, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2a, 0x00,
+ 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x28,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
+ 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00,
+ 0x00, 0x41, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x31,
+ 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
+ 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00,
+ 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x35, 0x00,
+ 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x36,
+ 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00,
+ 0x00, 0x39, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x37, 0x00,
+ 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x25,
+ 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00,
+ 0x00, 0x1b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3f, 0x00,
+ 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3d,
+ 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
+ 0x25, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x42, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x43, 0x00,
+ 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44,
+ 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
+ 0x42, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x47, 0x00,
+ 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x49, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00,
+ 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x22, 0x00,
+ 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x4e,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07,
+ 0x00, 0x19, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x4f, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00,
+ 0x00, 0xf9, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x12, 0x00, 0x00, 0x00, 0x41, 0x00,
+ 0x07, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00,
+ 0x00, 0x41, 0x00, 0x07, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00,
+ 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
+ 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0x62, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00,
+ 0x00, 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x5f,
+ 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00,
+ 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x69, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19,
+ 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x6b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00,
+ 0x00, 0x38, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6f,
+ 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x71, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x5f, 0x00,
+ 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x33,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x74, 0x00,
+ 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x75,
+ 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
+ 0x76, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07,
+ 0x00, 0x5f, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x79,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
+ 0x00, 0x7b, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x7a, 0x00,
+ 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x5e,
+ 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x81, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03,
+ 0x00, 0x78, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x85, 0x00,
+ 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x6c,
+ 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00,
+ 0x86, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x84, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05,
+ 0x00, 0x29, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x88,
+ 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00,
+ 0x00, 0x8c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x91, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x95, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x83, 0x00,
+ 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x3e,
+ 0x00, 0x03, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x98, 0x00, 0x00, 0x00,
+ 0x99, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x98, 0x00,
+ 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3d,
+ 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5f, 0x00, 0x00,
+ 0x00, 0x9e, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3d, 0x00,
+ 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xa1, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0xa2, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5f, 0x00, 0x00, 0x00, 0xa4,
+ 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0xa6, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa7, 0x00,
+ 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa8,
+ 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xa9, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa9, 0x00,
+ 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xaa,
+ 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00,
+ 0x00, 0xab, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x3e, 0x00,
+ 0x03, 0x00, 0xae, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xf8,
+ 0x00, 0x02, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xb3, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb3, 0x00, 0x00,
+ 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x7c, 0x00,
+ 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xb7,
+ 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x27, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00,
+ 0x00, 0xba, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x05, 0x00, 0xbb, 0x00,
+ 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xbc,
+ 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb0, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04,
+ 0x00, 0x0c, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x0c, 0x00,
+ 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x98,
+ 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00,
+ 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00,
+ 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5f, 0x00, 0x00, 0x00, 0xc4,
+ 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0xc6, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc7, 0x00,
+ 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc8,
+ 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xc9, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00,
+ 0x00, 0xae, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xca, 0x00,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5f, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x5e,
+ 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xcd, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00,
+ 0x00, 0x84, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0xcd, 0x00,
+ 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xc9,
+ 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00,
+ 0x8e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x31, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x50, 0x00,
+ 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0xd2,
+ 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00,
+ 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xb2, 0x00,
+ 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xd5,
+ 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00,
+ 0xd5, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xae, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00,
+ 0x00, 0xf9, 0x00, 0x02, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xf9, 0x00,
+ 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x14,
+ 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00,
+ 0xdd, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0xde, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x05, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xdf, 0x00,
+ 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xdf, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00,
+ 0xf8, 0x00, 0x02, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0xe3, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00,
+ 0x00, 0xe5, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0xda, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0xdc, 0x00,
+ 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, 0xe7,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x85, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00,
+ 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xe1, 0x00,
+ 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xed,
+ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xec, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00,
+ 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
+unsigned int vkvg_main_lcd_frag_spv_len = 5784;
+unsigned char wired_frag_spv[] = {
+ 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
+ 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00,
+ 0x00, 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x04,
+ 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f,
+ 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x09,
+ 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x61, 0x6e,
+ 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47,
+ 0x4c, 0x5f, 0x45, 0x58, 0x54, 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x61, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
+ 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47,
+ 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f,
+ 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x66, 0x6f, 0x6e, 0x74, 0x4d,
+ 0x61, 0x70, 0x00, 0x05, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00, 0x00,
+ 0x05, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x5f, 0x75, 0x62, 0x6f, 0x47, 0x72, 0x61, 0x64, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73,
+ 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x74, 0x6f, 0x70, 0x73,
+ 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x63, 0x70, 0x00, 0x00,
+ 0x06, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x75, 0x62, 0x6f, 0x47, 0x72, 0x61, 0x64, 0x00, 0x05, 0x00,
+ 0x05, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x46, 0x6f, 0x6e, 0x74, 0x55, 0x56, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x53, 0x72, 0x63, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x50, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05,
+ 0x00, 0x26, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x4f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x2b,
+ 0x00, 0x00, 0x00, 0x4e, 0x55, 0x4d, 0x5f, 0x53, 0x41, 0x4d, 0x50, 0x4c, 0x45, 0x53, 0x00, 0x47, 0x00, 0x04, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00,
+ 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x21, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x47, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04,
+ 0x00, 0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x19, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1a,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x47, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00,
+ 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x24,
+ 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x26, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04,
+ 0x00, 0x26, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2a, 0x00,
+ 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x2c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
+ 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00,
+ 0x09, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00,
+ 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1b, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04,
+ 0x00, 0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x14, 0x00,
+ 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
+ 0x3b, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x22, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x00,
+ 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x27,
+ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x27, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x32, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x36,
+ 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
+ 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
unsigned int wired_frag_spv_len = 1700;
/* stb_image - v2.19 - public domain image loader - http://nothings.org/stb
- no warranty implied; use at your own risk
+ no warranty implied; use at your own risk
Do this:
- #define STB_IMAGE_IMPLEMENTATION
+ #define STB_IMAGE_IMPLEMENTATION
before you include this file in *one* C or C++ file to create the implementation.
// i.e. it should look like this:
QUICK NOTES:
- Primarily of interest to game developers and other people who can
- avoid problematic images and only need the trivial interface
+ Primarily of interest to game developers and other people who can
+ avoid problematic images and only need the trivial interface
- JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib)
- PNG 1/2/4/8/16-bit-per-channel
+ JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib)
+ PNG 1/2/4/8/16-bit-per-channel
- TGA (not sure what subset, if a subset)
- BMP non-1bpp, non-RLE
- PSD (composited view only, no extra channels, 8/16 bit-per-channel)
+ TGA (not sure what subset, if a subset)
+ BMP non-1bpp, non-RLE
+ PSD (composited view only, no extra channels, 8/16 bit-per-channel)
- GIF (*comp always reports as 4-channel)
- HDR (radiance rgbE format)
- PIC (Softimage PIC)
- PNM (PPM and PGM binary only)
+ GIF (*comp always reports as 4-channel)
+ HDR (radiance rgbE format)
+ PIC (Softimage PIC)
+ PNM (PPM and PGM binary only)
- Animated GIF still needs a proper API, but here's one way to do it:
- http://gist.github.com/urraka/685d9a6340b26b830d49
+ Animated GIF still needs a proper API, but here's one way to do it:
+ http://gist.github.com/urraka/685d9a6340b26b830d49
- - decode from memory or through FILE (define STBI_NO_STDIO to remove code)
- - decode from arbitrary I/O callbacks
- - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON)
+ - decode from memory or through FILE (define STBI_NO_STDIO to remove code)
+ - decode from arbitrary I/O callbacks
+ - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON)
Full documentation under "DOCUMENTATION" below.
RECENT REVISION HISTORY:
- 2.19 (2018-02-11) fix warning
- 2.18 (2018-01-30) fix warnings
- 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings
- 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes
- 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC
- 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
- 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes
- 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
- 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
- RGB-format JPEG; remove white matting in PSD;
- allocate large structures on the stack;
- correct channel count for PNG & BMP
- 2.10 (2016-01-22) avoid warning introduced in 2.09
- 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
+ 2.19 (2018-02-11) fix warning
+ 2.18 (2018-01-30) fix warnings
+ 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings
+ 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes
+ 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC
+ 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
+ 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes
+ 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+ 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
+ RGB-format JPEG; remove white matting in PSD;
+ allocate large structures on the stack;
+ correct channel count for PNG & BMP
+ 2.10 (2016-01-22) avoid warning introduced in 2.09
+ 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
See end of file for full revision history.
============================ Contributors =========================
Image formats Extensions, features
- Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info)
- Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info)
- Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG)
- Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks)
- Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG)
- Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip)
- Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD)
- github:urraka (animated gif) Junggon Kim (PNM comments)
- Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA)
- socks-the-fox (16-bit PNG)
- Jeremy Sawicki (handle all ImageNet JPGs)
+ Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info)
+ Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info)
+ Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG)
+ Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks)
+ Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG)
+ Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip)
+ Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD)
+ github:urraka (animated gif) Junggon Kim (PNM comments)
+ Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA)
+ socks-the-fox (16-bit PNG)
+ Jeremy Sawicki (handle all ImageNet JPGs)
Optimizations & bugfixes Mikhail Morozov (1-bit BMP)
- Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query)
- Arseny Kapoulkine
- John-Mark Allen
+ Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query)
+ Arseny Kapoulkine
+ John-Mark Allen
Bug & warning fixes
- Marc LeBlanc David Woo Guillaume George Martins Mozeiko
- Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan
- Dave Moore Roy Eltham Hayaki Saito Nathan Reed
- Won Chun Luke Graham Johan Duparc Nick Verigakis
- the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh
- Janez Zemva John Bartholomew Michal Cichon github:romigrou
- Jonathan Blow Ken Hamada Tero Hanninen github:svdijk
- Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar
- Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex
- Ryamond Barbiero Paul Du Bois Engin Manap github:grim210
- Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw
- Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus
- Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo
- Christian Floisand Kevin Schmidt github:darealshinji
- Blazej Dariusz Roszkowski github:Michaelangel007
+ Marc LeBlanc David Woo Guillaume George Martins Mozeiko
+ Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan
+ Dave Moore Roy Eltham Hayaki Saito Nathan Reed
+ Won Chun Luke Graham Johan Duparc Nick Verigakis
+ the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh
+ Janez Zemva John Bartholomew Michal Cichon github:romigrou
+ Jonathan Blow Ken Hamada Tero Hanninen github:svdijk
+ Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar
+ Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex
+ Ryamond Barbiero Paul Du Bois Engin Manap github:grim210
+ Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw
+ Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus
+ Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo
+ Christian Floisand Kevin Schmidt github:darealshinji
+ Blazej Dariusz Roszkowski github:Michaelangel007
*/
#ifndef STBI_INCLUDE_STB_IMAGE_H
// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
//
-
#ifndef STBI_NO_STDIO
#include <stdio.h>
#endif // STBI_NO_STDIO
#define STBI_VERSION 1
-enum
-{
- STBI_default = 0, // only used for desired_channels
+enum {
+ STBI_default = 0, // only used for desired_channels
- STBI_grey = 1,
- STBI_grey_alpha = 2,
- STBI_rgb = 3,
- STBI_rgb_alpha = 4
+ STBI_grey = 1,
+ STBI_grey_alpha = 2,
+ STBI_rgb = 3,
+ STBI_rgb_alpha = 4
};
-typedef unsigned char stbi_uc;
+typedef unsigned char stbi_uc;
typedef unsigned short stbi_us;
#ifdef __cplusplus
// load image by filename, open file, or memory buffer
//
-typedef struct
-{
- int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read
- void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative
- int (*eof) (void *user); // returns nonzero if we are at end of file/data
+typedef struct {
+ int (*read)(void *user, char *data,
+ int size); // fill 'data' with 'size' bytes. return number of bytes actually read
+ void (*skip)(void *user, int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative
+ int (*eof)(void *user); // returns nonzero if we are at end of file/data
} stbi_io_callbacks;
////////////////////////////////////
// 8-bits-per-channel interface
//
-STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels);
-STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file,
+ int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y,
+ int *channels_in_file, int desired_channels);
#ifndef STBI_NO_GIF
-STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z,
+ int *comp, int req_comp);
#endif
-
#ifndef STBI_NO_STDIO
-STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
-STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
// for stbi_load_from_file, file pointer is left pointing immediately after image
#endif
// 16-bits-per-channel interface
//
-STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
-STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file,
+ int desired_channels);
+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y,
+ int *channels_in_file, int desired_channels);
#ifndef STBI_NO_STDIO
-STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
#endif
// float-per-channel interface
//
#ifndef STBI_NO_LINEAR
- STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
- STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file,
+ int desired_channels);
+STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y,
+ int *channels_in_file, int desired_channels);
- #ifndef STBI_NO_STDIO
- STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
- STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
- #endif
+#ifndef STBI_NO_STDIO
+STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+#endif
#endif
#ifndef STBI_NO_HDR
- STBIDEF void stbi_hdr_to_ldr_gamma(float gamma);
- STBIDEF void stbi_hdr_to_ldr_scale(float scale);
+STBIDEF void stbi_hdr_to_ldr_gamma(float gamma);
+STBIDEF void stbi_hdr_to_ldr_scale(float scale);
#endif // STBI_NO_HDR
#ifndef STBI_NO_LINEAR
- STBIDEF void stbi_ldr_to_hdr_gamma(float gamma);
- STBIDEF void stbi_ldr_to_hdr_scale(float scale);
+STBIDEF void stbi_ldr_to_hdr_gamma(float gamma);
+STBIDEF void stbi_ldr_to_hdr_scale(float scale);
#endif // STBI_NO_LINEAR
// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR
-STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
-STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
+STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
+STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
#ifndef STBI_NO_STDIO
-STBIDEF int stbi_is_hdr (char const *filename);
-STBIDEF int stbi_is_hdr_from_file(FILE *f);
+STBIDEF int stbi_is_hdr(char const *filename);
+STBIDEF int stbi_is_hdr_from_file(FILE *f);
#endif // STBI_NO_STDIO
-
// get a VERY brief reason for failure
// NOT THREADSAFE
-STBIDEF const char *stbi_failure_reason (void);
+STBIDEF const char *stbi_failure_reason(void);
// free the loaded image -- this is just free()
-STBIDEF void stbi_image_free (void *retval_from_stbi_load);
+STBIDEF void stbi_image_free(void *retval_from_stbi_load);
// get image dimensions & components without fully decoding
-STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
-STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
-STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len);
-STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user);
+STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
+STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
+STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len);
+STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user);
#ifndef STBI_NO_STDIO
-STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp);
-STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);
-STBIDEF int stbi_is_16_bit (char const *filename);
-STBIDEF int stbi_is_16_bit_from_file(FILE *f);
+STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp);
+STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp);
+STBIDEF int stbi_is_16_bit(char const *filename);
+STBIDEF int stbi_is_16_bit_from_file(FILE *f);
#endif
-
-
// for image formats that explicitly notate that they have premultiplied alpha,
// we just return the colors as stored in the file. set this flag to force
// unpremultiplication. results are undefined if the unpremultiply overflow.
// ZLIB client - used by PNG, available for other purposes
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
-STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
+STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen,
+ int parse_header);
STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
-STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
+STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
-STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
-
+STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
#ifdef __cplusplus
}
#ifdef STB_IMAGE_IMPLEMENTATION
-#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \
- || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \
- || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \
- || defined(STBI_ONLY_ZLIB)
- #ifndef STBI_ONLY_JPEG
- #define STBI_NO_JPEG
- #endif
- #ifndef STBI_ONLY_PNG
- #define STBI_NO_PNG
- #endif
- #ifndef STBI_ONLY_BMP
- #define STBI_NO_BMP
- #endif
- #ifndef STBI_ONLY_PSD
- #define STBI_NO_PSD
- #endif
- #ifndef STBI_ONLY_TGA
- #define STBI_NO_TGA
- #endif
- #ifndef STBI_ONLY_GIF
- #define STBI_NO_GIF
- #endif
- #ifndef STBI_ONLY_HDR
- #define STBI_NO_HDR
- #endif
- #ifndef STBI_ONLY_PIC
- #define STBI_NO_PIC
- #endif
- #ifndef STBI_ONLY_PNM
- #define STBI_NO_PNM
- #endif
+#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) || defined(STBI_ONLY_TGA) || \
+ defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || \
+ defined(STBI_ONLY_PNM) || defined(STBI_ONLY_ZLIB)
+#ifndef STBI_ONLY_JPEG
+#define STBI_NO_JPEG
+#endif
+#ifndef STBI_ONLY_PNG
+#define STBI_NO_PNG
+#endif
+#ifndef STBI_ONLY_BMP
+#define STBI_NO_BMP
+#endif
+#ifndef STBI_ONLY_PSD
+#define STBI_NO_PSD
+#endif
+#ifndef STBI_ONLY_TGA
+#define STBI_NO_TGA
+#endif
+#ifndef STBI_ONLY_GIF
+#define STBI_NO_GIF
+#endif
+#ifndef STBI_ONLY_HDR
+#define STBI_NO_HDR
+#endif
+#ifndef STBI_ONLY_PIC
+#define STBI_NO_PIC
+#endif
+#ifndef STBI_ONLY_PNM
+#define STBI_NO_PNM
+#endif
#endif
#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB)
#define STBI_NO_ZLIB
#endif
-
#include <stdarg.h>
#include <stddef.h> // ptrdiff_t on osx
#include <stdlib.h>
#include <limits.h>
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
-#include <math.h> // ldexp, pow
+#include <math.h> // ldexp, pow
#endif
#ifndef STBI_NO_STDIO
#define STBI_ASSERT(x) assert(x)
#endif
-
#ifndef _MSC_VER
- #ifdef __cplusplus
- #define stbi_inline inline
- #else
- #define stbi_inline
- #endif
+#ifdef __cplusplus
+#define stbi_inline inline
#else
- #define stbi_inline __forceinline
+#define stbi_inline
+#endif
+#else
+#define stbi_inline __forceinline
#endif
-
#ifdef _MSC_VER
typedef unsigned short stbi__uint16;
-typedef signed short stbi__int16;
+typedef signed short stbi__int16;
typedef unsigned int stbi__uint32;
-typedef signed int stbi__int32;
+typedef signed int stbi__int32;
#else
#include <stdint.h>
typedef uint16_t stbi__uint16;
-typedef int16_t stbi__int16;
+typedef int16_t stbi__int16;
typedef uint32_t stbi__uint32;
-typedef int32_t stbi__int32;
+typedef int32_t stbi__int32;
#endif
// should produce compiler error if size is wrong
-typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
+typedef unsigned char validate_uint32[sizeof(stbi__uint32) == 4 ? 1 : -1];
#ifdef _MSC_VER
-#define STBI_NOTUSED(v) (void)(v)
+#define STBI_NOTUSED(v) (void)(v)
#else
-#define STBI_NOTUSED(v) (void)sizeof(v)
+#define STBI_NOTUSED(v) (void)sizeof(v)
#endif
#ifdef _MSC_VER
#endif
#ifdef STBI_HAS_LROTL
- #define stbi_lrot(x,y) _lrotl(x,y)
+#define stbi_lrot(x, y) _lrotl(x, y)
#else
- #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y))))
+#define stbi_lrot(x, y) (((x) << (y)) | ((x) >> (32 - (y))))
#endif
#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED))
#endif
#ifndef STBI_MALLOC
-#define STBI_MALLOC(sz) malloc(sz)
-#define STBI_REALLOC(p,newsz) realloc(p,newsz)
-#define STBI_FREE(p) free(p)
+#define STBI_MALLOC(sz) malloc(sz)
+#define STBI_REALLOC(p, newsz) realloc(p, newsz)
+#define STBI_FREE(p) free(p)
#endif
#ifndef STBI_REALLOC_SIZED
-#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz)
+#define STBI_REALLOC_SIZED(p, oldsz, newsz) STBI_REALLOC(p, newsz)
#endif
// x86/x64 detection
#ifdef _MSC_VER
-#if _MSC_VER >= 1400 // not VC6
-#include <intrin.h> // __cpuid
-static int stbi__cpuid3(void)
-{
- int info[4];
- __cpuid(info,1);
- return info[3];
+#if _MSC_VER >= 1400 // not VC6
+#include <intrin.h> // __cpuid
+static int stbi__cpuid3(void) {
+ int info[4];
+ __cpuid(info, 1);
+ return info[3];
}
#else
-static int stbi__cpuid3(void)
-{
- int res;
- __asm {
+static int stbi__cpuid3(void) {
+ int res;
+ __asm {
mov eax,1
cpuid
mov res,edx
- }
- return res;
+ }
+ return res;
}
#endif
#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name
-static int stbi__sse2_available(void)
-{
- int info3 = stbi__cpuid3();
- return ((info3 >> 26) & 1) != 0;
+static int stbi__sse2_available(void) {
+ int info3 = stbi__cpuid3();
+ return ((info3 >> 26) & 1) != 0;
}
#else // assume GCC-style if not VC++
#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
-static int stbi__sse2_available(void)
-{
- // If we're even attempting to compile this on GCC/Clang, that means
- // -msse2 is on, which means the compiler is allowed to use SSE2
- // instructions at will, and so are we.
- return 1;
+static int stbi__sse2_available(void) {
+ // If we're even attempting to compile this on GCC/Clang, that means
+ // -msse2 is on, which means the compiler is allowed to use SSE2
+ // instructions at will, and so are we.
+ return 1;
}
#endif
#endif
// stbi__context structure is our basic context used by all images, so it
// contains all the IO context, plus some basic image information
-typedef struct
-{
- stbi__uint32 img_x, img_y;
- int img_n, img_out_n;
+typedef struct {
+ stbi__uint32 img_x, img_y;
+ int img_n, img_out_n;
- stbi_io_callbacks io;
- void *io_user_data;
+ stbi_io_callbacks io;
+ void *io_user_data;
- int read_from_callbacks;
- int buflen;
- stbi_uc buffer_start[128];
+ int read_from_callbacks;
+ int buflen;
+ stbi_uc buffer_start[128];
- stbi_uc *img_buffer, *img_buffer_end;
- stbi_uc *img_buffer_original, *img_buffer_original_end;
+ stbi_uc *img_buffer, *img_buffer_end;
+ stbi_uc *img_buffer_original, *img_buffer_original_end;
} stbi__context;
-
static void stbi__refill_buffer(stbi__context *s);
// initialize a memory-decode context
-static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
-{
- s->io.read = NULL;
- s->read_from_callbacks = 0;
- s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
- s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
+static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) {
+ s->io.read = NULL;
+ s->read_from_callbacks = 0;
+ s->img_buffer = s->img_buffer_original = (stbi_uc *)buffer;
+ s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *)buffer + len;
}
// initialize a callback-based context
-static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user)
-{
- s->io = *c;
- s->io_user_data = user;
- s->buflen = sizeof(s->buffer_start);
- s->read_from_callbacks = 1;
- s->img_buffer_original = s->buffer_start;
- stbi__refill_buffer(s);
- s->img_buffer_original_end = s->img_buffer_end;
+static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) {
+ s->io = *c;
+ s->io_user_data = user;
+ s->buflen = sizeof(s->buffer_start);
+ s->read_from_callbacks = 1;
+ s->img_buffer_original = s->buffer_start;
+ stbi__refill_buffer(s);
+ s->img_buffer_original_end = s->img_buffer_end;
}
#ifndef STBI_NO_STDIO
-static int stbi__stdio_read(void *user, char *data, int size)
-{
- return (int) fread(data,1,size,(FILE*) user);
-}
+static int stbi__stdio_read(void *user, char *data, int size) { return (int)fread(data, 1, size, (FILE *)user); }
-static void stbi__stdio_skip(void *user, int n)
-{
- fseek((FILE*) user, n, SEEK_CUR);
-}
+static void stbi__stdio_skip(void *user, int n) { fseek((FILE *)user, n, SEEK_CUR); }
-static int stbi__stdio_eof(void *user)
-{
- return feof((FILE*) user);
-}
+static int stbi__stdio_eof(void *user) { return feof((FILE *)user); }
-static stbi_io_callbacks stbi__stdio_callbacks =
-{
- stbi__stdio_read,
- stbi__stdio_skip,
- stbi__stdio_eof,
+static stbi_io_callbacks stbi__stdio_callbacks = {
+ stbi__stdio_read,
+ stbi__stdio_skip,
+ stbi__stdio_eof,
};
-static void stbi__start_file(stbi__context *s, FILE *f)
-{
- stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f);
-}
+static void stbi__start_file(stbi__context *s, FILE *f) { stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *)f); }
-//static void stop_file(stbi__context *s) { }
+// static void stop_file(stbi__context *s) { }
#endif // !STBI_NO_STDIO
-static void stbi__rewind(stbi__context *s)
-{
- // conceptually rewind SHOULD rewind to the beginning of the stream,
- // but we just rewind to the beginning of the initial buffer, because
- // we only use it after doing 'test', which only ever looks at at most 92 bytes
- s->img_buffer = s->img_buffer_original;
- s->img_buffer_end = s->img_buffer_original_end;
+static void stbi__rewind(stbi__context *s) {
+ // conceptually rewind SHOULD rewind to the beginning of the stream,
+ // but we just rewind to the beginning of the initial buffer, because
+ // we only use it after doing 'test', which only ever looks at at most 92 bytes
+ s->img_buffer = s->img_buffer_original;
+ s->img_buffer_end = s->img_buffer_original_end;
}
-enum
-{
- STBI_ORDER_RGB,
- STBI_ORDER_BGR
-};
+enum { STBI_ORDER_RGB, STBI_ORDER_BGR };
-typedef struct
-{
- int bits_per_channel;
- int num_channels;
- int channel_order;
+typedef struct {
+ int bits_per_channel;
+ int num_channels;
+ int channel_order;
} stbi__result_info;
#ifndef STBI_NO_JPEG
-static int stbi__jpeg_test(stbi__context *s);
-static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
-static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp);
+static int stbi__jpeg_test(stbi__context *s);
+static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_PNG
-static int stbi__png_test(stbi__context *s);
-static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
-static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp);
-static int stbi__png_is16(stbi__context *s);
+static int stbi__png_test(stbi__context *s);
+static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp);
+static int stbi__png_is16(stbi__context *s);
#endif
#ifndef STBI_NO_BMP
-static int stbi__bmp_test(stbi__context *s);
-static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
-static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp);
+static int stbi__bmp_test(stbi__context *s);
+static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_TGA
-static int stbi__tga_test(stbi__context *s);
-static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
-static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp);
+static int stbi__tga_test(stbi__context *s);
+static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_PSD
-static int stbi__psd_test(stbi__context *s);
-static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc);
-static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp);
-static int stbi__psd_is16(stbi__context *s);
+static int stbi__psd_test(stbi__context *s);
+static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc);
+static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp);
+static int stbi__psd_is16(stbi__context *s);
#endif
#ifndef STBI_NO_HDR
-static int stbi__hdr_test(stbi__context *s);
-static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
-static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp);
+static int stbi__hdr_test(stbi__context *s);
+static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_PIC
-static int stbi__pic_test(stbi__context *s);
-static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
-static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp);
+static int stbi__pic_test(stbi__context *s);
+static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_GIF
-static int stbi__gif_test(stbi__context *s);
-static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
-static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
-static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp);
+static int stbi__gif_test(stbi__context *s);
+static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
+static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_PNM
-static int stbi__pnm_test(stbi__context *s);
-static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
-static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
+static int stbi__pnm_test(stbi__context *s);
+static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
#endif
// this is not threadsafe
static const char *stbi__g_failure_reason;
-STBIDEF const char *stbi_failure_reason(void)
-{
- return stbi__g_failure_reason;
-}
+STBIDEF const char *stbi_failure_reason(void) { return stbi__g_failure_reason; }
-static int stbi__err(const char *str)
-{
- stbi__g_failure_reason = str;
- return 0;
+static int stbi__err(const char *str) {
+ stbi__g_failure_reason = str;
+ return 0;
}
-static void *stbi__malloc(size_t size)
-{
- return STBI_MALLOC(size);
-}
+static void *stbi__malloc(size_t size) { return STBI_MALLOC(size); }
// stb_image uses ints pervasively, including for offset calculations.
// therefore the largest decoded image size we can support with the
// return 1 if the sum is valid, 0 on overflow.
// negative terms are considered invalid.
-static int stbi__addsizes_valid(int a, int b)
-{
- if (b < 0) return 0;
- // now 0 <= b <= INT_MAX, hence also
- // 0 <= INT_MAX - b <= INTMAX.
- // And "a + b <= INT_MAX" (which might overflow) is the
- // same as a <= INT_MAX - b (no overflow)
- return a <= INT_MAX - b;
+static int stbi__addsizes_valid(int a, int b) {
+ if (b < 0)
+ return 0;
+ // now 0 <= b <= INT_MAX, hence also
+ // 0 <= INT_MAX - b <= INTMAX.
+ // And "a + b <= INT_MAX" (which might overflow) is the
+ // same as a <= INT_MAX - b (no overflow)
+ return a <= INT_MAX - b;
}
// returns 1 if the product is valid, 0 on overflow.
// negative factors are considered invalid.
-static int stbi__mul2sizes_valid(int a, int b)
-{
- if (a < 0 || b < 0) return 0;
- if (b == 0) return 1; // mul-by-0 is always safe
- // portable way to check for no overflows in a*b
- return a <= INT_MAX/b;
+static int stbi__mul2sizes_valid(int a, int b) {
+ if (a < 0 || b < 0)
+ return 0;
+ if (b == 0)
+ return 1; // mul-by-0 is always safe
+ // portable way to check for no overflows in a*b
+ return a <= INT_MAX / b;
}
// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow
-static int stbi__mad2sizes_valid(int a, int b, int add)
-{
- return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
+static int stbi__mad2sizes_valid(int a, int b, int add) {
+ return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a * b, add);
}
// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow
-static int stbi__mad3sizes_valid(int a, int b, int c, int add)
-{
- return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
- stbi__addsizes_valid(a*b*c, add);
+static int stbi__mad3sizes_valid(int a, int b, int c, int add) {
+ return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a * b, c) && stbi__addsizes_valid(a * b * c, add);
}
// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
-static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
-{
- return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
- stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add);
+static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) {
+ return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a * b, c) && stbi__mul2sizes_valid(a * b * c, d) &&
+ stbi__addsizes_valid(a * b * c * d, add);
}
#endif
// mallocs with size overflow checking
-static void *stbi__malloc_mad2(int a, int b, int add)
-{
- if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
- return stbi__malloc(a*b + add);
+static void *stbi__malloc_mad2(int a, int b, int add) {
+ if (!stbi__mad2sizes_valid(a, b, add))
+ return NULL;
+ return stbi__malloc(a * b + add);
}
-static void *stbi__malloc_mad3(int a, int b, int c, int add)
-{
- if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL;
- return stbi__malloc(a*b*c + add);
+static void *stbi__malloc_mad3(int a, int b, int c, int add) {
+ if (!stbi__mad3sizes_valid(a, b, c, add))
+ return NULL;
+ return stbi__malloc(a * b * c + add);
}
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
-static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
-{
- if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;
- return stbi__malloc(a*b*c*d + add);
+static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) {
+ if (!stbi__mad4sizes_valid(a, b, c, d, add))
+ return NULL;
+ return stbi__malloc(a * b * c * d + add);
}
#endif
// stbi__errpuc - error returning pointer to unsigned char
#ifdef STBI_NO_FAILURE_STRINGS
- #define stbi__err(x,y) 0
+#define stbi__err(x, y) 0
#elif defined(STBI_FAILURE_USERMSG)
- #define stbi__err(x,y) stbi__err(y)
+#define stbi__err(x, y) stbi__err(y)
#else
- #define stbi__err(x,y) stbi__err(x)
+#define stbi__err(x, y) stbi__err(x)
#endif
-#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL))
-#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL))
+#define stbi__errpf(x, y) ((float *)(size_t)(stbi__err(x, y) ? NULL : NULL))
+#define stbi__errpuc(x, y) ((unsigned char *)(size_t)(stbi__err(x, y) ? NULL : NULL))
-STBIDEF void stbi_image_free(void *retval_from_stbi_load)
-{
- STBI_FREE(retval_from_stbi_load);
-}
+STBIDEF void stbi_image_free(void *retval_from_stbi_load) { STBI_FREE(retval_from_stbi_load); }
#ifndef STBI_NO_LINEAR
-static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
+static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
#endif
#ifndef STBI_NO_HDR
-static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp);
+static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp);
#endif
static int stbi__vertically_flip_on_load = 0;
-STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
-{
- stbi__vertically_flip_on_load = flag_true_if_should_flip;
+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) {
+ stbi__vertically_flip_on_load = flag_true_if_should_flip;
}
-static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
-{
- memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
- ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed
- ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order
- ri->num_channels = 0;
-
- #ifndef STBI_NO_JPEG
- if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri);
- #endif
- #ifndef STBI_NO_PNG
- if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri);
- #endif
- #ifndef STBI_NO_BMP
- if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri);
- #endif
- #ifndef STBI_NO_GIF
- if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri);
- #endif
- #ifndef STBI_NO_PSD
- if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);
- #endif
- #ifndef STBI_NO_PIC
- if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri);
- #endif
- #ifndef STBI_NO_PNM
- if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri);
- #endif
-
- #ifndef STBI_NO_HDR
- if (stbi__hdr_test(s)) {
- float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri);
- return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
- }
- #endif
-
- #ifndef STBI_NO_TGA
- // test tga last because it's a crappy test!
- if (stbi__tga_test(s))
- return stbi__tga_load(s,x,y,comp,req_comp, ri);
- #endif
-
- return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");
-}
-
-static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels)
-{
- int i;
- int img_len = w * h * channels;
- stbi_uc *reduced;
+static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri,
+ int bpc) {
+ memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
+ ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed
+ ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order
+ ri->num_channels = 0;
- reduced = (stbi_uc *) stbi__malloc(img_len);
- if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory");
+#ifndef STBI_NO_JPEG
+ if (stbi__jpeg_test(s))
+ return stbi__jpeg_load(s, x, y, comp, req_comp, ri);
+#endif
+#ifndef STBI_NO_PNG
+ if (stbi__png_test(s))
+ return stbi__png_load(s, x, y, comp, req_comp, ri);
+#endif
+#ifndef STBI_NO_BMP
+ if (stbi__bmp_test(s))
+ return stbi__bmp_load(s, x, y, comp, req_comp, ri);
+#endif
+#ifndef STBI_NO_GIF
+ if (stbi__gif_test(s))
+ return stbi__gif_load(s, x, y, comp, req_comp, ri);
+#endif
+#ifndef STBI_NO_PSD
+ if (stbi__psd_test(s))
+ return stbi__psd_load(s, x, y, comp, req_comp, ri, bpc);
+#endif
+#ifndef STBI_NO_PIC
+ if (stbi__pic_test(s))
+ return stbi__pic_load(s, x, y, comp, req_comp, ri);
+#endif
+#ifndef STBI_NO_PNM
+ if (stbi__pnm_test(s))
+ return stbi__pnm_load(s, x, y, comp, req_comp, ri);
+#endif
+
+#ifndef STBI_NO_HDR
+ if (stbi__hdr_test(s)) {
+ float *hdr = stbi__hdr_load(s, x, y, comp, req_comp, ri);
+ return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
+ }
+#endif
- for (i = 0; i < img_len; ++i)
- reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling
+#ifndef STBI_NO_TGA
+ // test tga last because it's a crappy test!
+ if (stbi__tga_test(s))
+ return stbi__tga_load(s, x, y, comp, req_comp, ri);
+#endif
- STBI_FREE(orig);
- return reduced;
+ return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");
}
-static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels)
-{
- int i;
- int img_len = w * h * channels;
- stbi__uint16 *enlarged;
+static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) {
+ int i;
+ int img_len = w * h * channels;
+ stbi_uc *reduced;
- enlarged = (stbi__uint16 *) stbi__malloc(img_len*2);
- if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
+ reduced = (stbi_uc *)stbi__malloc(img_len);
+ if (reduced == NULL)
+ return stbi__errpuc("outofmem", "Out of memory");
- for (i = 0; i < img_len; ++i)
- enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff
+ for (i = 0; i < img_len; ++i)
+ reduced[i] =
+ (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling
- STBI_FREE(orig);
- return enlarged;
+ STBI_FREE(orig);
+ return reduced;
}
-static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)
-{
- int row;
- size_t bytes_per_row = (size_t)w * bytes_per_pixel;
- stbi_uc temp[2048];
- stbi_uc *bytes = (stbi_uc *)image;
-
- for (row = 0; row < (h>>1); row++) {
- stbi_uc *row0 = bytes + row*bytes_per_row;
- stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row;
- // swap row0 with row1
- size_t bytes_left = bytes_per_row;
- while (bytes_left) {
- size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp);
- memcpy(temp, row0, bytes_copy);
- memcpy(row0, row1, bytes_copy);
- memcpy(row1, temp, bytes_copy);
- row0 += bytes_copy;
- row1 += bytes_copy;
- bytes_left -= bytes_copy;
- }
- }
-}
-
-static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel)
-{
- int slice;
- int slice_size = w * h * bytes_per_pixel;
+static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) {
+ int i;
+ int img_len = w * h * channels;
+ stbi__uint16 *enlarged;
+
+ enlarged = (stbi__uint16 *)stbi__malloc(img_len * 2);
+ if (enlarged == NULL)
+ return (stbi__uint16 *)stbi__errpuc("outofmem", "Out of memory");
- stbi_uc *bytes = (stbi_uc *)image;
- for (slice = 0; slice < z; ++slice) {
- stbi__vertical_flip(bytes, w, h, bytes_per_pixel);
- bytes += slice_size;
- }
+ for (i = 0; i < img_len; ++i)
+ enlarged[i] =
+ (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff
+
+ STBI_FREE(orig);
+ return enlarged;
}
-static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
-{
- stbi__result_info ri;
- void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);
+static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) {
+ int row;
+ size_t bytes_per_row = (size_t)w * bytes_per_pixel;
+ stbi_uc temp[2048];
+ stbi_uc *bytes = (stbi_uc *)image;
+
+ for (row = 0; row < (h >> 1); row++) {
+ stbi_uc *row0 = bytes + row * bytes_per_row;
+ stbi_uc *row1 = bytes + (h - row - 1) * bytes_per_row;
+ // swap row0 with row1
+ size_t bytes_left = bytes_per_row;
+ while (bytes_left) {
+ size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp);
+ memcpy(temp, row0, bytes_copy);
+ memcpy(row0, row1, bytes_copy);
+ memcpy(row1, temp, bytes_copy);
+ row0 += bytes_copy;
+ row1 += bytes_copy;
+ bytes_left -= bytes_copy;
+ }
+ }
+}
+
+static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) {
+ int slice;
+ int slice_size = w * h * bytes_per_pixel;
+
+ stbi_uc *bytes = (stbi_uc *)image;
+ for (slice = 0; slice < z; ++slice) {
+ stbi__vertical_flip(bytes, w, h, bytes_per_pixel);
+ bytes += slice_size;
+ }
+}
+
+static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) {
+ stbi__result_info ri;
+ void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);
- if (result == NULL)
- return NULL;
+ if (result == NULL)
+ return NULL;
- if (ri.bits_per_channel != 8) {
- STBI_ASSERT(ri.bits_per_channel == 16);
- result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
- ri.bits_per_channel = 8;
- }
+ if (ri.bits_per_channel != 8) {
+ STBI_ASSERT(ri.bits_per_channel == 16);
+ result = stbi__convert_16_to_8((stbi__uint16 *)result, *x, *y, req_comp == 0 ? *comp : req_comp);
+ ri.bits_per_channel = 8;
+ }
- // @TODO: move stbi__convert_format to here
+ // @TODO: move stbi__convert_format to here
- if (stbi__vertically_flip_on_load) {
- int channels = req_comp ? req_comp : *comp;
- stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));
- }
+ if (stbi__vertically_flip_on_load) {
+ int channels = req_comp ? req_comp : *comp;
+ stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));
+ }
- return (unsigned char *) result;
+ return (unsigned char *)result;
}
-static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
-{
- stbi__result_info ri;
- void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16);
+static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) {
+ stbi__result_info ri;
+ void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16);
- if (result == NULL)
- return NULL;
+ if (result == NULL)
+ return NULL;
- if (ri.bits_per_channel != 16) {
- STBI_ASSERT(ri.bits_per_channel == 8);
- result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
- ri.bits_per_channel = 16;
- }
+ if (ri.bits_per_channel != 16) {
+ STBI_ASSERT(ri.bits_per_channel == 8);
+ result = stbi__convert_8_to_16((stbi_uc *)result, *x, *y, req_comp == 0 ? *comp : req_comp);
+ ri.bits_per_channel = 16;
+ }
- // @TODO: move stbi__convert_format16 to here
- // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision
+ // @TODO: move stbi__convert_format16 to here
+ // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision
- if (stbi__vertically_flip_on_load) {
- int channels = req_comp ? req_comp : *comp;
- stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16));
- }
+ if (stbi__vertically_flip_on_load) {
+ int channels = req_comp ? req_comp : *comp;
+ stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16));
+ }
- return (stbi__uint16 *) result;
+ return (stbi__uint16 *)result;
}
#if !defined(STBI_NO_HDR) || !defined(STBI_NO_LINEAR)
-static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
-{
- if (stbi__vertically_flip_on_load && result != NULL) {
- int channels = req_comp ? req_comp : *comp;
- stbi__vertical_flip(result, *x, *y, channels * sizeof(float));
- }
+static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) {
+ if (stbi__vertically_flip_on_load && result != NULL) {
+ int channels = req_comp ? req_comp : *comp;
+ stbi__vertical_flip(result, *x, *y, channels * sizeof(float));
+ }
}
#endif
#ifndef STBI_NO_STDIO
-static FILE *stbi__fopen(char const *filename, char const *mode)
-{
- FILE *f;
+static FILE *stbi__fopen(char const *filename, char const *mode) {
+ FILE *f;
#if defined(_MSC_VER) && _MSC_VER >= 1400
- if (0 != fopen_s(&f, filename, mode))
- f=0;
+ if (0 != fopen_s(&f, filename, mode))
+ f = 0;
#else
- f = fopen(filename, mode);
+ f = fopen(filename, mode);
#endif
- return f;
+ return f;
}
+STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) {
+ FILE *f = stbi__fopen(filename, "rb");
+ unsigned char *result;
+ if (!f)
+ return stbi__errpuc("can't fopen", "Unable to open file");
+ result = stbi_load_from_file(f, x, y, comp, req_comp);
+ fclose(f);
+ return result;
+}
-STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp)
-{
- FILE *f = stbi__fopen(filename, "rb");
- unsigned char *result;
- if (!f) return stbi__errpuc("can't fopen", "Unable to open file");
- result = stbi_load_from_file(f,x,y,comp,req_comp);
- fclose(f);
- return result;
+STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) {
+ unsigned char *result;
+ stbi__context s;
+ stbi__start_file(&s, f);
+ result = stbi__load_and_postprocess_8bit(&s, x, y, comp, req_comp);
+ if (result) {
+ // need to 'unget' all the characters in the IO buffer
+ fseek(f, -(int)(s.img_buffer_end - s.img_buffer), SEEK_CUR);
+ }
+ return result;
}
-STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
-{
- unsigned char *result;
- stbi__context s;
- stbi__start_file(&s,f);
- result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
- if (result) {
- // need to 'unget' all the characters in the IO buffer
- fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
- }
- return result;
-}
-
-STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp)
-{
- stbi__uint16 *result;
- stbi__context s;
- stbi__start_file(&s,f);
- result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp);
- if (result) {
- // need to 'unget' all the characters in the IO buffer
- fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
- }
- return result;
-}
-
-STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp)
-{
- FILE *f = stbi__fopen(filename, "rb");
- stbi__uint16 *result;
- if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file");
- result = stbi_load_from_file_16(f,x,y,comp,req_comp);
- fclose(f);
- return result;
+STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) {
+ stbi__uint16 *result;
+ stbi__context s;
+ stbi__start_file(&s, f);
+ result = stbi__load_and_postprocess_16bit(&s, x, y, comp, req_comp);
+ if (result) {
+ // need to 'unget' all the characters in the IO buffer
+ fseek(f, -(int)(s.img_buffer_end - s.img_buffer), SEEK_CUR);
+ }
+ return result;
}
+STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) {
+ FILE *f = stbi__fopen(filename, "rb");
+ stbi__uint16 *result;
+ if (!f)
+ return (stbi_us *)stbi__errpuc("can't fopen", "Unable to open file");
+ result = stbi_load_from_file_16(f, x, y, comp, req_comp);
+ fclose(f);
+ return result;
+}
-#endif //!STBI_NO_STDIO
+#endif //! STBI_NO_STDIO
-STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels)
-{
- stbi__context s;
- stbi__start_mem(&s,buffer,len);
- return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
+STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file,
+ int desired_channels) {
+ stbi__context s;
+ stbi__start_mem(&s, buffer, len);
+ return stbi__load_and_postprocess_16bit(&s, x, y, channels_in_file, desired_channels);
}
-STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels)
-{
- stbi__context s;
- stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
- return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y,
+ int *channels_in_file, int desired_channels) {
+ stbi__context s;
+ stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
+ return stbi__load_and_postprocess_16bit(&s, x, y, channels_in_file, desired_channels);
}
-STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
-{
- stbi__context s;
- stbi__start_mem(&s,buffer,len);
- return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) {
+ stbi__context s;
+ stbi__start_mem(&s, buffer, len);
+ return stbi__load_and_postprocess_8bit(&s, x, y, comp, req_comp);
}
-STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
-{
- stbi__context s;
- stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
- return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp,
+ int req_comp) {
+ stbi__context s;
+ stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
+ return stbi__load_and_postprocess_8bit(&s, x, y, comp, req_comp);
}
#ifndef STBI_NO_GIF
-STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
-{
- unsigned char *result;
- stbi__context s;
- stbi__start_mem(&s,buffer,len);
-
- result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp);
- if (stbi__vertically_flip_on_load) {
- stbi__vertical_flip_slices( result, *x, *y, *z, *comp );
- }
+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z,
+ int *comp, int req_comp) {
+ unsigned char *result;
+ stbi__context s;
+ stbi__start_mem(&s, buffer, len);
- return result;
+ result = (unsigned char *)stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp);
+ if (stbi__vertically_flip_on_load) {
+ stbi__vertical_flip_slices(result, *x, *y, *z, *comp);
+ }
+
+ return result;
}
#endif
#ifndef STBI_NO_LINEAR
-static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
-{
- unsigned char *data;
- #ifndef STBI_NO_HDR
- if (stbi__hdr_test(s)) {
- stbi__result_info ri;
- float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri);
- if (hdr_data)
- stbi__float_postprocess(hdr_data,x,y,comp,req_comp);
- return hdr_data;
- }
- #endif
- data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp);
- if (data)
- return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
- return stbi__errpf("unknown image type", "Image not of any known type, or corrupt");
-}
-
-STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
-{
- stbi__context s;
- stbi__start_mem(&s,buffer,len);
- return stbi__loadf_main(&s,x,y,comp,req_comp);
+static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) {
+ unsigned char *data;
+#ifndef STBI_NO_HDR
+ if (stbi__hdr_test(s)) {
+ stbi__result_info ri;
+ float *hdr_data = stbi__hdr_load(s, x, y, comp, req_comp, &ri);
+ if (hdr_data)
+ stbi__float_postprocess(hdr_data, x, y, comp, req_comp);
+ return hdr_data;
+ }
+#endif
+ data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp);
+ if (data)
+ return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
+ return stbi__errpf("unknown image type", "Image not of any known type, or corrupt");
}
-STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
-{
- stbi__context s;
- stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
- return stbi__loadf_main(&s,x,y,comp,req_comp);
+STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) {
+ stbi__context s;
+ stbi__start_mem(&s, buffer, len);
+ return stbi__loadf_main(&s, x, y, comp, req_comp);
+}
+
+STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp,
+ int req_comp) {
+ stbi__context s;
+ stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
+ return stbi__loadf_main(&s, x, y, comp, req_comp);
}
#ifndef STBI_NO_STDIO
-STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp)
-{
- float *result;
- FILE *f = stbi__fopen(filename, "rb");
- if (!f) return stbi__errpf("can't fopen", "Unable to open file");
- result = stbi_loadf_from_file(f,x,y,comp,req_comp);
- fclose(f);
- return result;
+STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) {
+ float *result;
+ FILE *f = stbi__fopen(filename, "rb");
+ if (!f)
+ return stbi__errpf("can't fopen", "Unable to open file");
+ result = stbi_loadf_from_file(f, x, y, comp, req_comp);
+ fclose(f);
+ return result;
}
-STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
-{
- stbi__context s;
- stbi__start_file(&s,f);
- return stbi__loadf_main(&s,x,y,comp,req_comp);
+STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) {
+ stbi__context s;
+ stbi__start_file(&s, f);
+ return stbi__loadf_main(&s, x, y, comp, req_comp);
}
#endif // !STBI_NO_STDIO
// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always
// reports false!
-STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len)
-{
- #ifndef STBI_NO_HDR
- stbi__context s;
- stbi__start_mem(&s,buffer,len);
- return stbi__hdr_test(&s);
- #else
- STBI_NOTUSED(buffer);
- STBI_NOTUSED(len);
- return 0;
- #endif
+STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) {
+#ifndef STBI_NO_HDR
+ stbi__context s;
+ stbi__start_mem(&s, buffer, len);
+ return stbi__hdr_test(&s);
+#else
+ STBI_NOTUSED(buffer);
+ STBI_NOTUSED(len);
+ return 0;
+#endif
}
#ifndef STBI_NO_STDIO
-STBIDEF int stbi_is_hdr (char const *filename)
-{
- FILE *f = stbi__fopen(filename, "rb");
- int result=0;
- if (f) {
- result = stbi_is_hdr_from_file(f);
- fclose(f);
- }
- return result;
+STBIDEF int stbi_is_hdr(char const *filename) {
+ FILE *f = stbi__fopen(filename, "rb");
+ int result = 0;
+ if (f) {
+ result = stbi_is_hdr_from_file(f);
+ fclose(f);
+ }
+ return result;
}
-STBIDEF int stbi_is_hdr_from_file(FILE *f)
-{
- #ifndef STBI_NO_HDR
- long pos = ftell(f);
- int res;
- stbi__context s;
- stbi__start_file(&s,f);
- res = stbi__hdr_test(&s);
- fseek(f, pos, SEEK_SET);
- return res;
- #else
- STBI_NOTUSED(f);
- return 0;
- #endif
+STBIDEF int stbi_is_hdr_from_file(FILE *f) {
+#ifndef STBI_NO_HDR
+ long pos = ftell(f);
+ int res;
+ stbi__context s;
+ stbi__start_file(&s, f);
+ res = stbi__hdr_test(&s);
+ fseek(f, pos, SEEK_SET);
+ return res;
+#else
+ STBI_NOTUSED(f);
+ return 0;
+#endif
}
#endif // !STBI_NO_STDIO
-STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user)
-{
- #ifndef STBI_NO_HDR
- stbi__context s;
- stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
- return stbi__hdr_test(&s);
- #else
- STBI_NOTUSED(clbk);
- STBI_NOTUSED(user);
- return 0;
- #endif
+STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) {
+#ifndef STBI_NO_HDR
+ stbi__context s;
+ stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
+ return stbi__hdr_test(&s);
+#else
+ STBI_NOTUSED(clbk);
+ STBI_NOTUSED(user);
+ return 0;
+#endif
}
#ifndef STBI_NO_LINEAR
-static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f;
+static float stbi__l2h_gamma = 2.2f, stbi__l2h_scale = 1.0f;
-STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; }
-STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }
+STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; }
+STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }
#endif
-static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f;
-
-STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; }
-STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; }
+static float stbi__h2l_gamma_i = 1.0f / 2.2f, stbi__h2l_scale_i = 1.0f;
+STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1 / gamma; }
+STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1 / scale; }
//////////////////////////////////////////////////////////////////////////////
//
// Common code used by all image loaders
//
-enum
-{
- STBI__SCAN_load=0,
- STBI__SCAN_type,
- STBI__SCAN_header
-};
-
-static void stbi__refill_buffer(stbi__context *s)
-{
- int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
- if (n == 0) {
- // at end of file, treat same as if from memory, but need to handle case
- // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
- s->read_from_callbacks = 0;
- s->img_buffer = s->buffer_start;
- s->img_buffer_end = s->buffer_start+1;
- *s->img_buffer = 0;
- } else {
- s->img_buffer = s->buffer_start;
- s->img_buffer_end = s->buffer_start + n;
- }
-}
-
-stbi_inline static stbi_uc stbi__get8(stbi__context *s)
-{
- if (s->img_buffer < s->img_buffer_end)
- return *s->img_buffer++;
- if (s->read_from_callbacks) {
- stbi__refill_buffer(s);
- return *s->img_buffer++;
- }
- return 0;
-}
-
-stbi_inline static int stbi__at_eof(stbi__context *s)
-{
- if (s->io.read) {
- if (!(s->io.eof)(s->io_user_data)) return 0;
- // if feof() is true, check if buffer = end
- // special case: we've only got the special 0 character at the end
- if (s->read_from_callbacks == 0) return 1;
- }
-
- return s->img_buffer >= s->img_buffer_end;
-}
-
-static void stbi__skip(stbi__context *s, int n)
-{
- if (n < 0) {
- s->img_buffer = s->img_buffer_end;
- return;
- }
- if (s->io.read) {
- int blen = (int) (s->img_buffer_end - s->img_buffer);
- if (blen < n) {
- s->img_buffer = s->img_buffer_end;
- (s->io.skip)(s->io_user_data, n - blen);
- return;
- }
- }
- s->img_buffer += n;
-}
-
-static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
-{
- if (s->io.read) {
- int blen = (int) (s->img_buffer_end - s->img_buffer);
- if (blen < n) {
- int res, count;
-
- memcpy(buffer, s->img_buffer, blen);
-
- count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen);
- res = (count == (n-blen));
- s->img_buffer = s->img_buffer_end;
- return res;
- }
- }
-
- if (s->img_buffer+n <= s->img_buffer_end) {
- memcpy(buffer, s->img_buffer, n);
- s->img_buffer += n;
- return 1;
- } else
- return 0;
-}
-
-static int stbi__get16be(stbi__context *s)
-{
- int z = stbi__get8(s);
- return (z << 8) + stbi__get8(s);
-}
-
-static stbi__uint32 stbi__get32be(stbi__context *s)
-{
- stbi__uint32 z = stbi__get16be(s);
- return (z << 16) + stbi__get16be(s);
+enum { STBI__SCAN_load = 0, STBI__SCAN_type, STBI__SCAN_header };
+
+static void stbi__refill_buffer(stbi__context *s) {
+ int n = (s->io.read)(s->io_user_data, (char *)s->buffer_start, s->buflen);
+ if (n == 0) {
+ // at end of file, treat same as if from memory, but need to handle case
+ // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
+ s->read_from_callbacks = 0;
+ s->img_buffer = s->buffer_start;
+ s->img_buffer_end = s->buffer_start + 1;
+ *s->img_buffer = 0;
+ } else {
+ s->img_buffer = s->buffer_start;
+ s->img_buffer_end = s->buffer_start + n;
+ }
+}
+
+stbi_inline static stbi_uc stbi__get8(stbi__context *s) {
+ if (s->img_buffer < s->img_buffer_end)
+ return *s->img_buffer++;
+ if (s->read_from_callbacks) {
+ stbi__refill_buffer(s);
+ return *s->img_buffer++;
+ }
+ return 0;
+}
+
+stbi_inline static int stbi__at_eof(stbi__context *s) {
+ if (s->io.read) {
+ if (!(s->io.eof)(s->io_user_data))
+ return 0;
+ // if feof() is true, check if buffer = end
+ // special case: we've only got the special 0 character at the end
+ if (s->read_from_callbacks == 0)
+ return 1;
+ }
+
+ return s->img_buffer >= s->img_buffer_end;
+}
+
+static void stbi__skip(stbi__context *s, int n) {
+ if (n < 0) {
+ s->img_buffer = s->img_buffer_end;
+ return;
+ }
+ if (s->io.read) {
+ int blen = (int)(s->img_buffer_end - s->img_buffer);
+ if (blen < n) {
+ s->img_buffer = s->img_buffer_end;
+ (s->io.skip)(s->io_user_data, n - blen);
+ return;
+ }
+ }
+ s->img_buffer += n;
+}
+
+static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) {
+ if (s->io.read) {
+ int blen = (int)(s->img_buffer_end - s->img_buffer);
+ if (blen < n) {
+ int res, count;
+
+ memcpy(buffer, s->img_buffer, blen);
+
+ count = (s->io.read)(s->io_user_data, (char *)buffer + blen, n - blen);
+ res = (count == (n - blen));
+ s->img_buffer = s->img_buffer_end;
+ return res;
+ }
+ }
+
+ if (s->img_buffer + n <= s->img_buffer_end) {
+ memcpy(buffer, s->img_buffer, n);
+ s->img_buffer += n;
+ return 1;
+ } else
+ return 0;
+}
+
+static int stbi__get16be(stbi__context *s) {
+ int z = stbi__get8(s);
+ return (z << 8) + stbi__get8(s);
+}
+
+static stbi__uint32 stbi__get32be(stbi__context *s) {
+ stbi__uint32 z = stbi__get16be(s);
+ return (z << 16) + stbi__get16be(s);
}
#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF)
// nothing
#else
-static int stbi__get16le(stbi__context *s)
-{
- int z = stbi__get8(s);
- return z + (stbi__get8(s) << 8);
+static int stbi__get16le(stbi__context *s) {
+ int z = stbi__get8(s);
+ return z + (stbi__get8(s) << 8);
}
#endif
#ifndef STBI_NO_BMP
-static stbi__uint32 stbi__get32le(stbi__context *s)
-{
- stbi__uint32 z = stbi__get16le(s);
- return z + (stbi__get16le(s) << 16);
+static stbi__uint32 stbi__get32le(stbi__context *s) {
+ stbi__uint32 z = stbi__get16le(s);
+ return z + (stbi__get16le(s) << 16);
}
#endif
-#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings
-
+#define STBI__BYTECAST(x) ((stbi_uc)((x)&255)) // truncate int to byte without warnings
//////////////////////////////////////////////////////////////////////////////
//
// assume data buffer is malloced, so malloc a new one and free that one
// only failure mode is malloc failing
-static stbi_uc stbi__compute_y(int r, int g, int b)
-{
- return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8);
-}
-
-static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y)
-{
- int i,j;
- unsigned char *good;
-
- if (req_comp == img_n) return data;
- STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
-
- good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0);
- if (good == NULL) {
- STBI_FREE(data);
- return stbi__errpuc("outofmem", "Out of memory");
- }
-
- for (j=0; j < (int) y; ++j) {
- unsigned char *src = data + j * x * img_n ;
- unsigned char *dest = good + j * x * req_comp;
-
- #define STBI__COMBO(a,b) ((a)*8+(b))
- #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
- // convert source image with img_n components to one with req_comp components;
- // avoid switch per pixel, so use switch per scanline and massive macros
- switch (STBI__COMBO(img_n, req_comp)) {
- STBI__CASE(1,2) { dest[0]=src[0], dest[1]=255; } break;
- STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
- STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; } break;
- STBI__CASE(2,1) { dest[0]=src[0]; } break;
- STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
- STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break;
- STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; } break;
- STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
- STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; } break;
- STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
- STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break;
- STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break;
- default: STBI_ASSERT(0);
- }
- #undef STBI__CASE
- }
-
- STBI_FREE(data);
- return good;
-}
-
-static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
-{
- return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8);
-}
-
-static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
-{
- int i,j;
- stbi__uint16 *good;
-
- if (req_comp == img_n) return data;
- STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
-
- good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2);
- if (good == NULL) {
- STBI_FREE(data);
- return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
- }
-
- for (j=0; j < (int) y; ++j) {
- stbi__uint16 *src = data + j * x * img_n ;
- stbi__uint16 *dest = good + j * x * req_comp;
-
- #define STBI__COMBO(a,b) ((a)*8+(b))
- #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
- // convert source image with img_n components to one with req_comp components;
- // avoid switch per pixel, so use switch per scanline and massive macros
- switch (STBI__COMBO(img_n, req_comp)) {
- STBI__CASE(1,2) { dest[0]=src[0], dest[1]=0xffff; } break;
- STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
- STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff; } break;
- STBI__CASE(2,1) { dest[0]=src[0]; } break;
- STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
- STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break;
- STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; } break;
- STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
- STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break;
- STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
- STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break;
- STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break;
- default: STBI_ASSERT(0);
- }
- #undef STBI__CASE
- }
-
- STBI_FREE(data);
- return good;
+static stbi_uc stbi__compute_y(int r, int g, int b) { return (stbi_uc)(((r * 77) + (g * 150) + (29 * b)) >> 8); }
+
+static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x,
+ unsigned int y) {
+ int i, j;
+ unsigned char *good;
+
+ if (req_comp == img_n)
+ return data;
+ STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
+
+ good = (unsigned char *)stbi__malloc_mad3(req_comp, x, y, 0);
+ if (good == NULL) {
+ STBI_FREE(data);
+ return stbi__errpuc("outofmem", "Out of memory");
+ }
+
+ for (j = 0; j < (int)y; ++j) {
+ unsigned char *src = data + j * x * img_n;
+ unsigned char *dest = good + j * x * req_comp;
+
+#define STBI__COMBO(a, b) ((a)*8 + (b))
+#define STBI__CASE(a, b) \
+ case STBI__COMBO(a, b): \
+ for (i = x - 1; i >= 0; --i, src += a, dest += b)
+ // convert source image with img_n components to one with req_comp components;
+ // avoid switch per pixel, so use switch per scanline and massive macros
+ switch (STBI__COMBO(img_n, req_comp)) {
+ STBI__CASE(1, 2) { dest[0] = src[0], dest[1] = 255; }
+ break;
+ STBI__CASE(1, 3) { dest[0] = dest[1] = dest[2] = src[0]; }
+ break;
+ STBI__CASE(1, 4) { dest[0] = dest[1] = dest[2] = src[0], dest[3] = 255; }
+ break;
+ STBI__CASE(2, 1) { dest[0] = src[0]; }
+ break;
+ STBI__CASE(2, 3) { dest[0] = dest[1] = dest[2] = src[0]; }
+ break;
+ STBI__CASE(2, 4) { dest[0] = dest[1] = dest[2] = src[0], dest[3] = src[1]; }
+ break;
+ STBI__CASE(3, 4) { dest[0] = src[0], dest[1] = src[1], dest[2] = src[2], dest[3] = 255; }
+ break;
+ STBI__CASE(3, 1) { dest[0] = stbi__compute_y(src[0], src[1], src[2]); }
+ break;
+ STBI__CASE(3, 2) { dest[0] = stbi__compute_y(src[0], src[1], src[2]), dest[1] = 255; }
+ break;
+ STBI__CASE(4, 1) { dest[0] = stbi__compute_y(src[0], src[1], src[2]); }
+ break;
+ STBI__CASE(4, 2) { dest[0] = stbi__compute_y(src[0], src[1], src[2]), dest[1] = src[3]; }
+ break;
+ STBI__CASE(4, 3) { dest[0] = src[0], dest[1] = src[1], dest[2] = src[2]; }
+ break;
+ default:
+ STBI_ASSERT(0);
+ }
+#undef STBI__CASE
+ }
+
+ STBI_FREE(data);
+ return good;
+}
+
+static stbi__uint16 stbi__compute_y_16(int r, int g, int b) {
+ return (stbi__uint16)(((r * 77) + (g * 150) + (29 * b)) >> 8);
+}
+
+static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x,
+ unsigned int y) {
+ int i, j;
+ stbi__uint16 *good;
+
+ if (req_comp == img_n)
+ return data;
+ STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
+
+ good = (stbi__uint16 *)stbi__malloc(req_comp * x * y * 2);
+ if (good == NULL) {
+ STBI_FREE(data);
+ return (stbi__uint16 *)stbi__errpuc("outofmem", "Out of memory");
+ }
+
+ for (j = 0; j < (int)y; ++j) {
+ stbi__uint16 *src = data + j * x * img_n;
+ stbi__uint16 *dest = good + j * x * req_comp;
+
+#define STBI__COMBO(a, b) ((a)*8 + (b))
+#define STBI__CASE(a, b) \
+ case STBI__COMBO(a, b): \
+ for (i = x - 1; i >= 0; --i, src += a, dest += b)
+ // convert source image with img_n components to one with req_comp components;
+ // avoid switch per pixel, so use switch per scanline and massive macros
+ switch (STBI__COMBO(img_n, req_comp)) {
+ STBI__CASE(1, 2) { dest[0] = src[0], dest[1] = 0xffff; }
+ break;
+ STBI__CASE(1, 3) { dest[0] = dest[1] = dest[2] = src[0]; }
+ break;
+ STBI__CASE(1, 4) { dest[0] = dest[1] = dest[2] = src[0], dest[3] = 0xffff; }
+ break;
+ STBI__CASE(2, 1) { dest[0] = src[0]; }
+ break;
+ STBI__CASE(2, 3) { dest[0] = dest[1] = dest[2] = src[0]; }
+ break;
+ STBI__CASE(2, 4) { dest[0] = dest[1] = dest[2] = src[0], dest[3] = src[1]; }
+ break;
+ STBI__CASE(3, 4) { dest[0] = src[0], dest[1] = src[1], dest[2] = src[2], dest[3] = 0xffff; }
+ break;
+ STBI__CASE(3, 1) { dest[0] = stbi__compute_y_16(src[0], src[1], src[2]); }
+ break;
+ STBI__CASE(3, 2) { dest[0] = stbi__compute_y_16(src[0], src[1], src[2]), dest[1] = 0xffff; }
+ break;
+ STBI__CASE(4, 1) { dest[0] = stbi__compute_y_16(src[0], src[1], src[2]); }
+ break;
+ STBI__CASE(4, 2) { dest[0] = stbi__compute_y_16(src[0], src[1], src[2]), dest[1] = src[3]; }
+ break;
+ STBI__CASE(4, 3) { dest[0] = src[0], dest[1] = src[1], dest[2] = src[2]; }
+ break;
+ default:
+ STBI_ASSERT(0);
+ }
+#undef STBI__CASE
+ }
+
+ STBI_FREE(data);
+ return good;
}
#ifndef STBI_NO_LINEAR
-static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
-{
- int i,k,n;
- float *output;
- if (!data) return NULL;
- output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
- if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); }
- // compute number of non-alpha components
- if (comp & 1) n = comp; else n = comp-1;
- for (i=0; i < x*y; ++i) {
- for (k=0; k < n; ++k) {
- output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale);
- }
- if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f;
- }
- STBI_FREE(data);
- return output;
+static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) {
+ int i, k, n;
+ float *output;
+ if (!data)
+ return NULL;
+ output = (float *)stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
+ if (output == NULL) {
+ STBI_FREE(data);
+ return stbi__errpf("outofmem", "Out of memory");
+ }
+ // compute number of non-alpha components
+ if (comp & 1)
+ n = comp;
+ else
+ n = comp - 1;
+ for (i = 0; i < x * y; ++i) {
+ for (k = 0; k < n; ++k) {
+ output[i * comp + k] = (float)(pow(data[i * comp + k] / 255.0f, stbi__l2h_gamma) * stbi__l2h_scale);
+ }
+ if (k < comp)
+ output[i * comp + k] = data[i * comp + k] / 255.0f;
+ }
+ STBI_FREE(data);
+ return output;
}
#endif
#ifndef STBI_NO_HDR
-#define stbi__float2int(x) ((int) (x))
-static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp)
-{
- int i,k,n;
- stbi_uc *output;
- if (!data) return NULL;
- output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0);
- if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); }
- // compute number of non-alpha components
- if (comp & 1) n = comp; else n = comp-1;
- for (i=0; i < x*y; ++i) {
- for (k=0; k < n; ++k) {
- float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f;
- if (z < 0) z = 0;
- if (z > 255) z = 255;
- output[i*comp + k] = (stbi_uc) stbi__float2int(z);
- }
- if (k < comp) {
- float z = data[i*comp+k] * 255 + 0.5f;
- if (z < 0) z = 0;
- if (z > 255) z = 255;
- output[i*comp + k] = (stbi_uc) stbi__float2int(z);
- }
- }
- STBI_FREE(data);
- return output;
+#define stbi__float2int(x) ((int)(x))
+static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) {
+ int i, k, n;
+ stbi_uc *output;
+ if (!data)
+ return NULL;
+ output = (stbi_uc *)stbi__malloc_mad3(x, y, comp, 0);
+ if (output == NULL) {
+ STBI_FREE(data);
+ return stbi__errpuc("outofmem", "Out of memory");
+ }
+ // compute number of non-alpha components
+ if (comp & 1)
+ n = comp;
+ else
+ n = comp - 1;
+ for (i = 0; i < x * y; ++i) {
+ for (k = 0; k < n; ++k) {
+ float z = (float)pow(data[i * comp + k] * stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f;
+ if (z < 0)
+ z = 0;
+ if (z > 255)
+ z = 255;
+ output[i * comp + k] = (stbi_uc)stbi__float2int(z);
+ }
+ if (k < comp) {
+ float z = data[i * comp + k] * 255 + 0.5f;
+ if (z < 0)
+ z = 0;
+ if (z > 255)
+ z = 255;
+ output[i * comp + k] = (stbi_uc)stbi__float2int(z);
+ }
+ }
+ STBI_FREE(data);
+ return output;
}
#endif
#ifndef STBI_NO_JPEG
// huffman decoding acceleration
-#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache
-
-typedef struct
-{
- stbi_uc fast[1 << FAST_BITS];
- // weirdly, repacking this into AoS is a 10% speed loss, instead of a win
- stbi__uint16 code[256];
- stbi_uc values[256];
- stbi_uc size[257];
- unsigned int maxcode[18];
- int delta[17]; // old 'firstsymbol' - old 'firstcode'
+#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache
+
+typedef struct {
+ stbi_uc fast[1 << FAST_BITS];
+ // weirdly, repacking this into AoS is a 10% speed loss, instead of a win
+ stbi__uint16 code[256];
+ stbi_uc values[256];
+ stbi_uc size[257];
+ unsigned int maxcode[18];
+ int delta[17]; // old 'firstsymbol' - old 'firstcode'
} stbi__huffman;
-typedef struct
-{
- stbi__context *s;
- stbi__huffman huff_dc[4];
- stbi__huffman huff_ac[4];
- stbi__uint16 dequant[4][64];
- stbi__int16 fast_ac[4][1 << FAST_BITS];
-
-// sizes for components, interleaved MCUs
- int img_h_max, img_v_max;
- int img_mcu_x, img_mcu_y;
- int img_mcu_w, img_mcu_h;
-
-// definition of jpeg image component
- struct
- {
- int id;
- int h,v;
- int tq;
- int hd,ha;
- int dc_pred;
-
- int x,y,w2,h2;
- stbi_uc *data;
- void *raw_data, *raw_coeff;
- stbi_uc *linebuf;
- short *coeff; // progressive only
- int coeff_w, coeff_h; // number of 8x8 coefficient blocks
- } img_comp[4];
-
- stbi__uint32 code_buffer; // jpeg entropy-coded buffer
- int code_bits; // number of valid bits
- unsigned char marker; // marker seen while filling entropy buffer
- int nomore; // flag if we saw a marker so must stop
-
- int progressive;
- int spec_start;
- int spec_end;
- int succ_high;
- int succ_low;
- int eob_run;
- int jfif;
- int app14_color_transform; // Adobe APP14 tag
- int rgb;
-
- int scan_n, order[4];
- int restart_interval, todo;
-
-// kernels
- void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]);
- void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step);
- stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs);
+typedef struct {
+ stbi__context *s;
+ stbi__huffman huff_dc[4];
+ stbi__huffman huff_ac[4];
+ stbi__uint16 dequant[4][64];
+ stbi__int16 fast_ac[4][1 << FAST_BITS];
+
+ // sizes for components, interleaved MCUs
+ int img_h_max, img_v_max;
+ int img_mcu_x, img_mcu_y;
+ int img_mcu_w, img_mcu_h;
+
+ // definition of jpeg image component
+ struct {
+ int id;
+ int h, v;
+ int tq;
+ int hd, ha;
+ int dc_pred;
+
+ int x, y, w2, h2;
+ stbi_uc *data;
+ void *raw_data, *raw_coeff;
+ stbi_uc *linebuf;
+ short *coeff; // progressive only
+ int coeff_w, coeff_h; // number of 8x8 coefficient blocks
+ } img_comp[4];
+
+ stbi__uint32 code_buffer; // jpeg entropy-coded buffer
+ int code_bits; // number of valid bits
+ unsigned char marker; // marker seen while filling entropy buffer
+ int nomore; // flag if we saw a marker so must stop
+
+ int progressive;
+ int spec_start;
+ int spec_end;
+ int succ_high;
+ int succ_low;
+ int eob_run;
+ int jfif;
+ int app14_color_transform; // Adobe APP14 tag
+ int rgb;
+
+ int scan_n, order[4];
+ int restart_interval, todo;
+
+ // kernels
+ void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]);
+ void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count,
+ int step);
+ stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs);
} stbi__jpeg;
-static int stbi__build_huffman(stbi__huffman *h, int *count)
-{
- int i,j,k=0;
- unsigned int code;
- // build size list for each symbol (from JPEG spec)
- for (i=0; i < 16; ++i)
- for (j=0; j < count[i]; ++j)
- h->size[k++] = (stbi_uc) (i+1);
- h->size[k] = 0;
-
- // compute actual symbols (from jpeg spec)
- code = 0;
- k = 0;
- for(j=1; j <= 16; ++j) {
- // compute delta to add to code to compute symbol id
- h->delta[j] = k - code;
- if (h->size[k] == j) {
- while (h->size[k] == j)
- h->code[k++] = (stbi__uint16) (code++);
- if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG");
- }
- // compute largest code + 1 for this size, preshifted as needed later
- h->maxcode[j] = code << (16-j);
- code <<= 1;
- }
- h->maxcode[j] = 0xffffffff;
-
- // build non-spec acceleration table; 255 is flag for not-accelerated
- memset(h->fast, 255, 1 << FAST_BITS);
- for (i=0; i < k; ++i) {
- int s = h->size[i];
- if (s <= FAST_BITS) {
- int c = h->code[i] << (FAST_BITS-s);
- int m = 1 << (FAST_BITS-s);
- for (j=0; j < m; ++j) {
- h->fast[c+j] = (stbi_uc) i;
- }
- }
- }
- return 1;
+static int stbi__build_huffman(stbi__huffman *h, int *count) {
+ int i, j, k = 0;
+ unsigned int code;
+ // build size list for each symbol (from JPEG spec)
+ for (i = 0; i < 16; ++i)
+ for (j = 0; j < count[i]; ++j)
+ h->size[k++] = (stbi_uc)(i + 1);
+ h->size[k] = 0;
+
+ // compute actual symbols (from jpeg spec)
+ code = 0;
+ k = 0;
+ for (j = 1; j <= 16; ++j) {
+ // compute delta to add to code to compute symbol id
+ h->delta[j] = k - code;
+ if (h->size[k] == j) {
+ while (h->size[k] == j)
+ h->code[k++] = (stbi__uint16)(code++);
+ if (code - 1 >= (1u << j))
+ return stbi__err("bad code lengths", "Corrupt JPEG");
+ }
+ // compute largest code + 1 for this size, preshifted as needed later
+ h->maxcode[j] = code << (16 - j);
+ code <<= 1;
+ }
+ h->maxcode[j] = 0xffffffff;
+
+ // build non-spec acceleration table; 255 is flag for not-accelerated
+ memset(h->fast, 255, 1 << FAST_BITS);
+ for (i = 0; i < k; ++i) {
+ int s = h->size[i];
+ if (s <= FAST_BITS) {
+ int c = h->code[i] << (FAST_BITS - s);
+ int m = 1 << (FAST_BITS - s);
+ for (j = 0; j < m; ++j) {
+ h->fast[c + j] = (stbi_uc)i;
+ }
+ }
+ }
+ return 1;
}
// build a table that decodes both magnitude and value of small ACs in
// one go.
-static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h)
-{
- int i;
- for (i=0; i < (1 << FAST_BITS); ++i) {
- stbi_uc fast = h->fast[i];
- fast_ac[i] = 0;
- if (fast < 255) {
- int rs = h->values[fast];
- int run = (rs >> 4) & 15;
- int magbits = rs & 15;
- int len = h->size[fast];
-
- if (magbits && len + magbits <= FAST_BITS) {
- // magnitude code followed by receive_extend code
- int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits);
- int m = 1 << (magbits - 1);
- if (k < m) k += (~0U << magbits) + 1;
- // if the result is small enough, we can fit it in fast_ac table
- if (k >= -128 && k <= 127)
- fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits));
- }
- }
- }
-}
-
-static void stbi__grow_buffer_unsafe(stbi__jpeg *j)
-{
- do {
- unsigned int b = j->nomore ? 0 : stbi__get8(j->s);
- if (b == 0xff) {
- int c = stbi__get8(j->s);
- while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes
- if (c != 0) {
- j->marker = (unsigned char) c;
- j->nomore = 1;
- return;
- }
- }
- j->code_buffer |= b << (24 - j->code_bits);
- j->code_bits += 8;
- } while (j->code_bits <= 24);
+static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) {
+ int i;
+ for (i = 0; i < (1 << FAST_BITS); ++i) {
+ stbi_uc fast = h->fast[i];
+ fast_ac[i] = 0;
+ if (fast < 255) {
+ int rs = h->values[fast];
+ int run = (rs >> 4) & 15;
+ int magbits = rs & 15;
+ int len = h->size[fast];
+
+ if (magbits && len + magbits <= FAST_BITS) {
+ // magnitude code followed by receive_extend code
+ int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits);
+ int m = 1 << (magbits - 1);
+ if (k < m)
+ k += (~0U << magbits) + 1;
+ // if the result is small enough, we can fit it in fast_ac table
+ if (k >= -128 && k <= 127)
+ fast_ac[i] = (stbi__int16)((k * 256) + (run * 16) + (len + magbits));
+ }
+ }
+ }
+}
+
+static void stbi__grow_buffer_unsafe(stbi__jpeg *j) {
+ do {
+ unsigned int b = j->nomore ? 0 : stbi__get8(j->s);
+ if (b == 0xff) {
+ int c = stbi__get8(j->s);
+ while (c == 0xff)
+ c = stbi__get8(j->s); // consume fill bytes
+ if (c != 0) {
+ j->marker = (unsigned char)c;
+ j->nomore = 1;
+ return;
+ }
+ }
+ j->code_buffer |= b << (24 - j->code_bits);
+ j->code_bits += 8;
+ } while (j->code_bits <= 24);
}
// (1 << n) - 1
-static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535};
+static const stbi__uint32 stbi__bmask[17] = {0, 1, 3, 7, 15, 31, 63, 127, 255,
+ 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535};
// decode a jpeg huffman value from the bitstream
-stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h)
-{
- unsigned int temp;
- int c,k;
-
- if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
-
- // look at the top FAST_BITS and determine what symbol ID it is,
- // if the code is <= FAST_BITS
- c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
- k = h->fast[c];
- if (k < 255) {
- int s = h->size[k];
- if (s > j->code_bits)
- return -1;
- j->code_buffer <<= s;
- j->code_bits -= s;
- return h->values[k];
- }
-
- // naive test is to shift the code_buffer down so k bits are
- // valid, then test against maxcode. To speed this up, we've
- // preshifted maxcode left so that it has (16-k) 0s at the
- // end; in other words, regardless of the number of bits, it
- // wants to be compared against something shifted to have 16;
- // that way we don't need to shift inside the loop.
- temp = j->code_buffer >> 16;
- for (k=FAST_BITS+1 ; ; ++k)
- if (temp < h->maxcode[k])
- break;
- if (k == 17) {
- // error! code not found
- j->code_bits -= 16;
- return -1;
- }
-
- if (k > j->code_bits)
- return -1;
-
- // convert the huffman code to the symbol id
- c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k];
- STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]);
-
- // convert the id to a symbol
- j->code_bits -= k;
- j->code_buffer <<= k;
- return h->values[c];
+stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) {
+ unsigned int temp;
+ int c, k;
+
+ if (j->code_bits < 16)
+ stbi__grow_buffer_unsafe(j);
+
+ // look at the top FAST_BITS and determine what symbol ID it is,
+ // if the code is <= FAST_BITS
+ c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS) - 1);
+ k = h->fast[c];
+ if (k < 255) {
+ int s = h->size[k];
+ if (s > j->code_bits)
+ return -1;
+ j->code_buffer <<= s;
+ j->code_bits -= s;
+ return h->values[k];
+ }
+
+ // naive test is to shift the code_buffer down so k bits are
+ // valid, then test against maxcode. To speed this up, we've
+ // preshifted maxcode left so that it has (16-k) 0s at the
+ // end; in other words, regardless of the number of bits, it
+ // wants to be compared against something shifted to have 16;
+ // that way we don't need to shift inside the loop.
+ temp = j->code_buffer >> 16;
+ for (k = FAST_BITS + 1;; ++k)
+ if (temp < h->maxcode[k])
+ break;
+ if (k == 17) {
+ // error! code not found
+ j->code_bits -= 16;
+ return -1;
+ }
+
+ if (k > j->code_bits)
+ return -1;
+
+ // convert the huffman code to the symbol id
+ c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k];
+ STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]);
+
+ // convert the id to a symbol
+ j->code_bits -= k;
+ j->code_buffer <<= k;
+ return h->values[c];
}
// bias[n] = (-1<<n) + 1
-static const int stbi__jbias[16] = {0,-1,-3,-7,-15,-31,-63,-127,-255,-511,-1023,-2047,-4095,-8191,-16383,-32767};
+static const int stbi__jbias[16] = {0, -1, -3, -7, -15, -31, -63, -127,
+ -255, -511, -1023, -2047, -4095, -8191, -16383, -32767};
// combined JPEG 'receive' and JPEG 'extend', since baseline
// always extends everything it receives.
-stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
-{
- unsigned int k;
- int sgn;
- if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
+stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n) {
+ unsigned int k;
+ int sgn;
+ if (j->code_bits < n)
+ stbi__grow_buffer_unsafe(j);
- sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
- k = stbi_lrot(j->code_buffer, n);
- STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask)));
- j->code_buffer = k & ~stbi__bmask[n];
- k &= stbi__bmask[n];
- j->code_bits -= n;
- return k + (stbi__jbias[n] & ~sgn);
+ sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
+ k = stbi_lrot(j->code_buffer, n);
+ STBI_ASSERT(n >= 0 && n < (int)(sizeof(stbi__bmask) / sizeof(*stbi__bmask)));
+ j->code_buffer = k & ~stbi__bmask[n];
+ k &= stbi__bmask[n];
+ j->code_bits -= n;
+ return k + (stbi__jbias[n] & ~sgn);
}
// get some unsigned bits
-stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n)
-{
- unsigned int k;
- if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
- k = stbi_lrot(j->code_buffer, n);
- j->code_buffer = k & ~stbi__bmask[n];
- k &= stbi__bmask[n];
- j->code_bits -= n;
- return k;
-}
-
-stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j)
-{
- unsigned int k;
- if (j->code_bits < 1) stbi__grow_buffer_unsafe(j);
- k = j->code_buffer;
- j->code_buffer <<= 1;
- --j->code_bits;
- return k & 0x80000000;
+stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) {
+ unsigned int k;
+ if (j->code_bits < n)
+ stbi__grow_buffer_unsafe(j);
+ k = stbi_lrot(j->code_buffer, n);
+ j->code_buffer = k & ~stbi__bmask[n];
+ k &= stbi__bmask[n];
+ j->code_bits -= n;
+ return k;
+}
+
+stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) {
+ unsigned int k;
+ if (j->code_bits < 1)
+ stbi__grow_buffer_unsafe(j);
+ k = j->code_buffer;
+ j->code_buffer <<= 1;
+ --j->code_bits;
+ return k & 0x80000000;
}
// given a value that's at position X in the zigzag stream,
// where does it appear in the 8x8 matrix coded as row-major?
-static const stbi_uc stbi__jpeg_dezigzag[64+15] =
-{
- 0, 1, 8, 16, 9, 2, 3, 10,
- 17, 24, 32, 25, 18, 11, 4, 5,
- 12, 19, 26, 33, 40, 48, 41, 34,
- 27, 20, 13, 6, 7, 14, 21, 28,
- 35, 42, 49, 56, 57, 50, 43, 36,
- 29, 22, 15, 23, 30, 37, 44, 51,
- 58, 59, 52, 45, 38, 31, 39, 46,
- 53, 60, 61, 54, 47, 55, 62, 63,
- // let corrupt input sample past end
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63
-};
+static const stbi_uc stbi__jpeg_dezigzag[64 + 15] = {0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26,
+ 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56,
+ 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38,
+ 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
+ // let corrupt input sample past end
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63};
// decode one 64-entry block--
-static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant)
-{
- int diff,dc,k;
- int t;
-
- if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
- t = stbi__jpeg_huff_decode(j, hdc);
- if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG");
-
- // 0 all the ac values now so we can do it 32-bits at a time
- memset(data,0,64*sizeof(data[0]));
-
- diff = t ? stbi__extend_receive(j, t) : 0;
- dc = j->img_comp[b].dc_pred + diff;
- j->img_comp[b].dc_pred = dc;
- data[0] = (short) (dc * dequant[0]);
-
- // decode AC components, see JPEG spec
- k = 1;
- do {
- unsigned int zig;
- int c,r,s;
- if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
- c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
- r = fac[c];
- if (r) { // fast-AC path
- k += (r >> 4) & 15; // run
- s = r & 15; // combined length
- j->code_buffer <<= s;
- j->code_bits -= s;
- // decode into unzigzag'd location
- zig = stbi__jpeg_dezigzag[k++];
- data[zig] = (short) ((r >> 8) * dequant[zig]);
- } else {
- int rs = stbi__jpeg_huff_decode(j, hac);
- if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
- s = rs & 15;
- r = rs >> 4;
- if (s == 0) {
- if (rs != 0xf0) break; // end block
- k += 16;
- } else {
- k += r;
- // decode into unzigzag'd location
- zig = stbi__jpeg_dezigzag[k++];
- data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]);
- }
- }
- } while (k < 64);
- return 1;
-}
-
-static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b)
-{
- int diff,dc;
- int t;
- if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
-
- if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
-
- if (j->succ_high == 0) {
- // first scan for DC coefficient, must be first
- memset(data,0,64*sizeof(data[0])); // 0 all the ac values now
- t = stbi__jpeg_huff_decode(j, hdc);
- diff = t ? stbi__extend_receive(j, t) : 0;
-
- dc = j->img_comp[b].dc_pred + diff;
- j->img_comp[b].dc_pred = dc;
- data[0] = (short) (dc << j->succ_low);
- } else {
- // refinement scan for DC coefficient
- if (stbi__jpeg_get_bit(j))
- data[0] += (short) (1 << j->succ_low);
- }
- return 1;
+static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac,
+ stbi__int16 *fac, int b, stbi__uint16 *dequant) {
+ int diff, dc, k;
+ int t;
+
+ if (j->code_bits < 16)
+ stbi__grow_buffer_unsafe(j);
+ t = stbi__jpeg_huff_decode(j, hdc);
+ if (t < 0)
+ return stbi__err("bad huffman code", "Corrupt JPEG");
+
+ // 0 all the ac values now so we can do it 32-bits at a time
+ memset(data, 0, 64 * sizeof(data[0]));
+
+ diff = t ? stbi__extend_receive(j, t) : 0;
+ dc = j->img_comp[b].dc_pred + diff;
+ j->img_comp[b].dc_pred = dc;
+ data[0] = (short)(dc * dequant[0]);
+
+ // decode AC components, see JPEG spec
+ k = 1;
+ do {
+ unsigned int zig;
+ int c, r, s;
+ if (j->code_bits < 16)
+ stbi__grow_buffer_unsafe(j);
+ c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS) - 1);
+ r = fac[c];
+ if (r) { // fast-AC path
+ k += (r >> 4) & 15; // run
+ s = r & 15; // combined length
+ j->code_buffer <<= s;
+ j->code_bits -= s;
+ // decode into unzigzag'd location
+ zig = stbi__jpeg_dezigzag[k++];
+ data[zig] = (short)((r >> 8) * dequant[zig]);
+ } else {
+ int rs = stbi__jpeg_huff_decode(j, hac);
+ if (rs < 0)
+ return stbi__err("bad huffman code", "Corrupt JPEG");
+ s = rs & 15;
+ r = rs >> 4;
+ if (s == 0) {
+ if (rs != 0xf0)
+ break; // end block
+ k += 16;
+ } else {
+ k += r;
+ // decode into unzigzag'd location
+ zig = stbi__jpeg_dezigzag[k++];
+ data[zig] = (short)(stbi__extend_receive(j, s) * dequant[zig]);
+ }
+ }
+ } while (k < 64);
+ return 1;
+}
+
+static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) {
+ int diff, dc;
+ int t;
+ if (j->spec_end != 0)
+ return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+
+ if (j->code_bits < 16)
+ stbi__grow_buffer_unsafe(j);
+
+ if (j->succ_high == 0) {
+ // first scan for DC coefficient, must be first
+ memset(data, 0, 64 * sizeof(data[0])); // 0 all the ac values now
+ t = stbi__jpeg_huff_decode(j, hdc);
+ diff = t ? stbi__extend_receive(j, t) : 0;
+
+ dc = j->img_comp[b].dc_pred + diff;
+ j->img_comp[b].dc_pred = dc;
+ data[0] = (short)(dc << j->succ_low);
+ } else {
+ // refinement scan for DC coefficient
+ if (stbi__jpeg_get_bit(j))
+ data[0] += (short)(1 << j->succ_low);
+ }
+ return 1;
}
// @OPTIMIZE: store non-zigzagged during the decode passes,
// and only de-zigzag when dequantizing
-static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac)
-{
- int k;
- if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
-
- if (j->succ_high == 0) {
- int shift = j->succ_low;
-
- if (j->eob_run) {
- --j->eob_run;
- return 1;
- }
-
- k = j->spec_start;
- do {
- unsigned int zig;
- int c,r,s;
- if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
- c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
- r = fac[c];
- if (r) { // fast-AC path
- k += (r >> 4) & 15; // run
- s = r & 15; // combined length
- j->code_buffer <<= s;
- j->code_bits -= s;
- zig = stbi__jpeg_dezigzag[k++];
- data[zig] = (short) ((r >> 8) << shift);
- } else {
- int rs = stbi__jpeg_huff_decode(j, hac);
- if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
- s = rs & 15;
- r = rs >> 4;
- if (s == 0) {
- if (r < 15) {
- j->eob_run = (1 << r);
- if (r)
- j->eob_run += stbi__jpeg_get_bits(j, r);
- --j->eob_run;
- break;
- }
- k += 16;
- } else {
- k += r;
- zig = stbi__jpeg_dezigzag[k++];
- data[zig] = (short) (stbi__extend_receive(j,s) << shift);
- }
- }
- } while (k <= j->spec_end);
- } else {
- // refinement scan for these AC coefficients
-
- short bit = (short) (1 << j->succ_low);
-
- if (j->eob_run) {
- --j->eob_run;
- for (k = j->spec_start; k <= j->spec_end; ++k) {
- short *p = &data[stbi__jpeg_dezigzag[k]];
- if (*p != 0)
- if (stbi__jpeg_get_bit(j))
- if ((*p & bit)==0) {
- if (*p > 0)
- *p += bit;
- else
- *p -= bit;
- }
- }
- } else {
- k = j->spec_start;
- do {
- int r,s;
- int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh
- if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
- s = rs & 15;
- r = rs >> 4;
- if (s == 0) {
- if (r < 15) {
- j->eob_run = (1 << r) - 1;
- if (r)
- j->eob_run += stbi__jpeg_get_bits(j, r);
- r = 64; // force end of block
- } else {
- // r=15 s=0 should write 16 0s, so we just do
- // a run of 15 0s and then write s (which is 0),
- // so we don't have to do anything special here
- }
- } else {
- if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG");
- // sign bit
- if (stbi__jpeg_get_bit(j))
- s = bit;
- else
- s = -bit;
- }
-
- // advance by r
- while (k <= j->spec_end) {
- short *p = &data[stbi__jpeg_dezigzag[k++]];
- if (*p != 0) {
- if (stbi__jpeg_get_bit(j))
- if ((*p & bit)==0) {
- if (*p > 0)
- *p += bit;
- else
- *p -= bit;
- }
- } else {
- if (r == 0) {
- *p = (short) s;
- break;
- }
- --r;
- }
- }
- } while (k <= j->spec_end);
- }
- }
- return 1;
+static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) {
+ int k;
+ if (j->spec_start == 0)
+ return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+
+ if (j->succ_high == 0) {
+ int shift = j->succ_low;
+
+ if (j->eob_run) {
+ --j->eob_run;
+ return 1;
+ }
+
+ k = j->spec_start;
+ do {
+ unsigned int zig;
+ int c, r, s;
+ if (j->code_bits < 16)
+ stbi__grow_buffer_unsafe(j);
+ c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS) - 1);
+ r = fac[c];
+ if (r) { // fast-AC path
+ k += (r >> 4) & 15; // run
+ s = r & 15; // combined length
+ j->code_buffer <<= s;
+ j->code_bits -= s;
+ zig = stbi__jpeg_dezigzag[k++];
+ data[zig] = (short)((r >> 8) << shift);
+ } else {
+ int rs = stbi__jpeg_huff_decode(j, hac);
+ if (rs < 0)
+ return stbi__err("bad huffman code", "Corrupt JPEG");
+ s = rs & 15;
+ r = rs >> 4;
+ if (s == 0) {
+ if (r < 15) {
+ j->eob_run = (1 << r);
+ if (r)
+ j->eob_run += stbi__jpeg_get_bits(j, r);
+ --j->eob_run;
+ break;
+ }
+ k += 16;
+ } else {
+ k += r;
+ zig = stbi__jpeg_dezigzag[k++];
+ data[zig] = (short)(stbi__extend_receive(j, s) << shift);
+ }
+ }
+ } while (k <= j->spec_end);
+ } else {
+ // refinement scan for these AC coefficients
+
+ short bit = (short)(1 << j->succ_low);
+
+ if (j->eob_run) {
+ --j->eob_run;
+ for (k = j->spec_start; k <= j->spec_end; ++k) {
+ short *p = &data[stbi__jpeg_dezigzag[k]];
+ if (*p != 0)
+ if (stbi__jpeg_get_bit(j))
+ if ((*p & bit) == 0) {
+ if (*p > 0)
+ *p += bit;
+ else
+ *p -= bit;
+ }
+ }
+ } else {
+ k = j->spec_start;
+ do {
+ int r, s;
+ int rs = stbi__jpeg_huff_decode(
+ j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh
+ if (rs < 0)
+ return stbi__err("bad huffman code", "Corrupt JPEG");
+ s = rs & 15;
+ r = rs >> 4;
+ if (s == 0) {
+ if (r < 15) {
+ j->eob_run = (1 << r) - 1;
+ if (r)
+ j->eob_run += stbi__jpeg_get_bits(j, r);
+ r = 64; // force end of block
+ } else {
+ // r=15 s=0 should write 16 0s, so we just do
+ // a run of 15 0s and then write s (which is 0),
+ // so we don't have to do anything special here
+ }
+ } else {
+ if (s != 1)
+ return stbi__err("bad huffman code", "Corrupt JPEG");
+ // sign bit
+ if (stbi__jpeg_get_bit(j))
+ s = bit;
+ else
+ s = -bit;
+ }
+
+ // advance by r
+ while (k <= j->spec_end) {
+ short *p = &data[stbi__jpeg_dezigzag[k++]];
+ if (*p != 0) {
+ if (stbi__jpeg_get_bit(j))
+ if ((*p & bit) == 0) {
+ if (*p > 0)
+ *p += bit;
+ else
+ *p -= bit;
+ }
+ } else {
+ if (r == 0) {
+ *p = (short)s;
+ break;
+ }
+ --r;
+ }
+ }
+ } while (k <= j->spec_end);
+ }
+ }
+ return 1;
}
// take a -128..127 value and stbi__clamp it and convert to 0..255
-stbi_inline static stbi_uc stbi__clamp(int x)
-{
- // trick to use a single test to catch both cases
- if ((unsigned int) x > 255) {
- if (x < 0) return 0;
- if (x > 255) return 255;
- }
- return (stbi_uc) x;
+stbi_inline static stbi_uc stbi__clamp(int x) {
+ // trick to use a single test to catch both cases
+ if ((unsigned int)x > 255) {
+ if (x < 0)
+ return 0;
+ if (x > 255)
+ return 255;
+ }
+ return (stbi_uc)x;
}
-#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5)))
-#define stbi__fsh(x) ((x) * 4096)
+#define stbi__f2f(x) ((int)(((x)*4096 + 0.5)))
+#define stbi__fsh(x) ((x)*4096)
// derived from jidctint -- DCT_ISLOW
-#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \
- int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \
- p2 = s2; \
- p3 = s6; \
- p1 = (p2+p3) * stbi__f2f(0.5411961f); \
- t2 = p1 + p3*stbi__f2f(-1.847759065f); \
- t3 = p1 + p2*stbi__f2f( 0.765366865f); \
- p2 = s0; \
- p3 = s4; \
- t0 = stbi__fsh(p2+p3); \
- t1 = stbi__fsh(p2-p3); \
- x0 = t0+t3; \
- x3 = t0-t3; \
- x1 = t1+t2; \
- x2 = t1-t2; \
- t0 = s7; \
- t1 = s5; \
- t2 = s3; \
- t3 = s1; \
- p3 = t0+t2; \
- p4 = t1+t3; \
- p1 = t0+t3; \
- p2 = t1+t2; \
- p5 = (p3+p4)*stbi__f2f( 1.175875602f); \
- t0 = t0*stbi__f2f( 0.298631336f); \
- t1 = t1*stbi__f2f( 2.053119869f); \
- t2 = t2*stbi__f2f( 3.072711026f); \
- t3 = t3*stbi__f2f( 1.501321110f); \
- p1 = p5 + p1*stbi__f2f(-0.899976223f); \
- p2 = p5 + p2*stbi__f2f(-2.562915447f); \
- p3 = p3*stbi__f2f(-1.961570560f); \
- p4 = p4*stbi__f2f(-0.390180644f); \
- t3 += p1+p4; \
- t2 += p2+p3; \
- t1 += p2+p4; \
- t0 += p1+p3;
-
-static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64])
-{
- int i,val[64],*v=val;
- stbi_uc *o;
- short *d = data;
-
- // columns
- for (i=0; i < 8; ++i,++d, ++v) {
- // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing
- if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0
- && d[40]==0 && d[48]==0 && d[56]==0) {
- // no shortcut 0 seconds
- // (1|2|3|4|5|6|7)==0 0 seconds
- // all separate -0.047 seconds
- // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds
- int dcterm = d[0]*4;
- v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm;
- } else {
- STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56])
- // constants scaled things up by 1<<12; let's bring them back
- // down, but keep 2 extra bits of precision
- x0 += 512; x1 += 512; x2 += 512; x3 += 512;
- v[ 0] = (x0+t3) >> 10;
- v[56] = (x0-t3) >> 10;
- v[ 8] = (x1+t2) >> 10;
- v[48] = (x1-t2) >> 10;
- v[16] = (x2+t1) >> 10;
- v[40] = (x2-t1) >> 10;
- v[24] = (x3+t0) >> 10;
- v[32] = (x3-t0) >> 10;
- }
- }
-
- for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) {
- // no fast case since the first 1D IDCT spread components out
- STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7])
- // constants scaled things up by 1<<12, plus we had 1<<2 from first
- // loop, plus horizontal and vertical each scale by sqrt(8) so together
- // we've got an extra 1<<3, so 1<<17 total we need to remove.
- // so we want to round that, which means adding 0.5 * 1<<17,
- // aka 65536. Also, we'll end up with -128 to 127 that we want
- // to encode as 0..255 by adding 128, so we'll add that before the shift
- x0 += 65536 + (128<<17);
- x1 += 65536 + (128<<17);
- x2 += 65536 + (128<<17);
- x3 += 65536 + (128<<17);
- // tried computing the shifts into temps, or'ing the temps to see
- // if any were out of range, but that was slower
- o[0] = stbi__clamp((x0+t3) >> 17);
- o[7] = stbi__clamp((x0-t3) >> 17);
- o[1] = stbi__clamp((x1+t2) >> 17);
- o[6] = stbi__clamp((x1-t2) >> 17);
- o[2] = stbi__clamp((x2+t1) >> 17);
- o[5] = stbi__clamp((x2-t1) >> 17);
- o[3] = stbi__clamp((x3+t0) >> 17);
- o[4] = stbi__clamp((x3-t0) >> 17);
- }
+#define STBI__IDCT_1D(s0, s1, s2, s3, s4, s5, s6, s7) \
+ int t0, t1, t2, t3, p1, p2, p3, p4, p5, x0, x1, x2, x3; \
+ p2 = s2; \
+ p3 = s6; \
+ p1 = (p2 + p3) * stbi__f2f(0.5411961f); \
+ t2 = p1 + p3 * stbi__f2f(-1.847759065f); \
+ t3 = p1 + p2 * stbi__f2f(0.765366865f); \
+ p2 = s0; \
+ p3 = s4; \
+ t0 = stbi__fsh(p2 + p3); \
+ t1 = stbi__fsh(p2 - p3); \
+ x0 = t0 + t3; \
+ x3 = t0 - t3; \
+ x1 = t1 + t2; \
+ x2 = t1 - t2; \
+ t0 = s7; \
+ t1 = s5; \
+ t2 = s3; \
+ t3 = s1; \
+ p3 = t0 + t2; \
+ p4 = t1 + t3; \
+ p1 = t0 + t3; \
+ p2 = t1 + t2; \
+ p5 = (p3 + p4) * stbi__f2f(1.175875602f); \
+ t0 = t0 * stbi__f2f(0.298631336f); \
+ t1 = t1 * stbi__f2f(2.053119869f); \
+ t2 = t2 * stbi__f2f(3.072711026f); \
+ t3 = t3 * stbi__f2f(1.501321110f); \
+ p1 = p5 + p1 * stbi__f2f(-0.899976223f); \
+ p2 = p5 + p2 * stbi__f2f(-2.562915447f); \
+ p3 = p3 * stbi__f2f(-1.961570560f); \
+ p4 = p4 * stbi__f2f(-0.390180644f); \
+ t3 += p1 + p4; \
+ t2 += p2 + p3; \
+ t1 += p2 + p4; \
+ t0 += p1 + p3;
+
+static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) {
+ int i, val[64], *v = val;
+ stbi_uc *o;
+ short *d = data;
+
+ // columns
+ for (i = 0; i < 8; ++i, ++d, ++v) {
+ // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing
+ if (d[8] == 0 && d[16] == 0 && d[24] == 0 && d[32] == 0 && d[40] == 0 && d[48] == 0 && d[56] == 0) {
+ // no shortcut 0 seconds
+ // (1|2|3|4|5|6|7)==0 0 seconds
+ // all separate -0.047 seconds
+ // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds
+ int dcterm = d[0] * 4;
+ v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm;
+ } else {
+ STBI__IDCT_1D(d[0], d[8], d[16], d[24], d[32], d[40], d[48], d[56])
+ // constants scaled things up by 1<<12; let's bring them back
+ // down, but keep 2 extra bits of precision
+ x0 += 512;
+ x1 += 512;
+ x2 += 512;
+ x3 += 512;
+ v[0] = (x0 + t3) >> 10;
+ v[56] = (x0 - t3) >> 10;
+ v[8] = (x1 + t2) >> 10;
+ v[48] = (x1 - t2) >> 10;
+ v[16] = (x2 + t1) >> 10;
+ v[40] = (x2 - t1) >> 10;
+ v[24] = (x3 + t0) >> 10;
+ v[32] = (x3 - t0) >> 10;
+ }
+ }
+
+ for (i = 0, v = val, o = out; i < 8; ++i, v += 8, o += out_stride) {
+ // no fast case since the first 1D IDCT spread components out
+ STBI__IDCT_1D(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7])
+ // constants scaled things up by 1<<12, plus we had 1<<2 from first
+ // loop, plus horizontal and vertical each scale by sqrt(8) so together
+ // we've got an extra 1<<3, so 1<<17 total we need to remove.
+ // so we want to round that, which means adding 0.5 * 1<<17,
+ // aka 65536. Also, we'll end up with -128 to 127 that we want
+ // to encode as 0..255 by adding 128, so we'll add that before the shift
+ x0 += 65536 + (128 << 17);
+ x1 += 65536 + (128 << 17);
+ x2 += 65536 + (128 << 17);
+ x3 += 65536 + (128 << 17);
+ // tried computing the shifts into temps, or'ing the temps to see
+ // if any were out of range, but that was slower
+ o[0] = stbi__clamp((x0 + t3) >> 17);
+ o[7] = stbi__clamp((x0 - t3) >> 17);
+ o[1] = stbi__clamp((x1 + t2) >> 17);
+ o[6] = stbi__clamp((x1 - t2) >> 17);
+ o[2] = stbi__clamp((x2 + t1) >> 17);
+ o[5] = stbi__clamp((x2 - t1) >> 17);
+ o[3] = stbi__clamp((x3 + t0) >> 17);
+ o[4] = stbi__clamp((x3 - t0) >> 17);
+ }
}
#ifdef STBI_SSE2
// sse2 integer IDCT. not the fastest possible implementation but it
// produces bit-identical results to the generic C version so it's
// fully "transparent".
-static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
-{
- // This is constructed to match our regular (generic) integer IDCT exactly.
- __m128i row0, row1, row2, row3, row4, row5, row6, row7;
- __m128i tmp;
-
- // dot product constant: even elems=x, odd elems=y
- #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y))
-
- // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit)
- // out(1) = c1[even]*x + c1[odd]*y
- #define dct_rot(out0,out1, x,y,c0,c1) \
- __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \
- __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \
- __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \
- __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \
- __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \
- __m128i out1##_h = _mm_madd_epi16(c0##hi, c1)
-
- // out = in << 12 (in 16-bit, out 32-bit)
- #define dct_widen(out, in) \
- __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \
- __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4)
-
- // wide add
- #define dct_wadd(out, a, b) \
- __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \
- __m128i out##_h = _mm_add_epi32(a##_h, b##_h)
-
- // wide sub
- #define dct_wsub(out, a, b) \
- __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \
- __m128i out##_h = _mm_sub_epi32(a##_h, b##_h)
-
- // butterfly a/b, add bias, then shift by "s" and pack
- #define dct_bfly32o(out0, out1, a,b,bias,s) \
- { \
- __m128i abiased_l = _mm_add_epi32(a##_l, bias); \
- __m128i abiased_h = _mm_add_epi32(a##_h, bias); \
- dct_wadd(sum, abiased, b); \
- dct_wsub(dif, abiased, b); \
- out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \
- out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \
- }
-
- // 8-bit interleave step (for transposes)
- #define dct_interleave8(a, b) \
- tmp = a; \
- a = _mm_unpacklo_epi8(a, b); \
- b = _mm_unpackhi_epi8(tmp, b)
-
- // 16-bit interleave step (for transposes)
- #define dct_interleave16(a, b) \
- tmp = a; \
- a = _mm_unpacklo_epi16(a, b); \
- b = _mm_unpackhi_epi16(tmp, b)
-
- #define dct_pass(bias,shift) \
- { \
- /* even part */ \
- dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \
- __m128i sum04 = _mm_add_epi16(row0, row4); \
- __m128i dif04 = _mm_sub_epi16(row0, row4); \
- dct_widen(t0e, sum04); \
- dct_widen(t1e, dif04); \
- dct_wadd(x0, t0e, t3e); \
- dct_wsub(x3, t0e, t3e); \
- dct_wadd(x1, t1e, t2e); \
- dct_wsub(x2, t1e, t2e); \
- /* odd part */ \
- dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \
- dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \
- __m128i sum17 = _mm_add_epi16(row1, row7); \
- __m128i sum35 = _mm_add_epi16(row3, row5); \
- dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \
- dct_wadd(x4, y0o, y4o); \
- dct_wadd(x5, y1o, y5o); \
- dct_wadd(x6, y2o, y5o); \
- dct_wadd(x7, y3o, y4o); \
- dct_bfly32o(row0,row7, x0,x7,bias,shift); \
- dct_bfly32o(row1,row6, x1,x6,bias,shift); \
- dct_bfly32o(row2,row5, x2,x5,bias,shift); \
- dct_bfly32o(row3,row4, x3,x4,bias,shift); \
- }
-
- __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f));
- __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f));
- __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f));
- __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f));
- __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f));
- __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f));
- __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f));
- __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f));
-
- // rounding biases in column/row passes, see stbi__idct_block for explanation.
- __m128i bias_0 = _mm_set1_epi32(512);
- __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17));
-
- // load
- row0 = _mm_load_si128((const __m128i *) (data + 0*8));
- row1 = _mm_load_si128((const __m128i *) (data + 1*8));
- row2 = _mm_load_si128((const __m128i *) (data + 2*8));
- row3 = _mm_load_si128((const __m128i *) (data + 3*8));
- row4 = _mm_load_si128((const __m128i *) (data + 4*8));
- row5 = _mm_load_si128((const __m128i *) (data + 5*8));
- row6 = _mm_load_si128((const __m128i *) (data + 6*8));
- row7 = _mm_load_si128((const __m128i *) (data + 7*8));
-
- // column pass
- dct_pass(bias_0, 10);
-
- {
- // 16bit 8x8 transpose pass 1
- dct_interleave16(row0, row4);
- dct_interleave16(row1, row5);
- dct_interleave16(row2, row6);
- dct_interleave16(row3, row7);
-
- // transpose pass 2
- dct_interleave16(row0, row2);
- dct_interleave16(row1, row3);
- dct_interleave16(row4, row6);
- dct_interleave16(row5, row7);
-
- // transpose pass 3
- dct_interleave16(row0, row1);
- dct_interleave16(row2, row3);
- dct_interleave16(row4, row5);
- dct_interleave16(row6, row7);
- }
-
- // row pass
- dct_pass(bias_1, 17);
-
- {
- // pack
- __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7
- __m128i p1 = _mm_packus_epi16(row2, row3);
- __m128i p2 = _mm_packus_epi16(row4, row5);
- __m128i p3 = _mm_packus_epi16(row6, row7);
-
- // 8bit 8x8 transpose pass 1
- dct_interleave8(p0, p2); // a0e0a1e1...
- dct_interleave8(p1, p3); // c0g0c1g1...
-
- // transpose pass 2
- dct_interleave8(p0, p1); // a0c0e0g0...
- dct_interleave8(p2, p3); // b0d0f0h0...
-
- // transpose pass 3
- dct_interleave8(p0, p2); // a0b0c0d0...
- dct_interleave8(p1, p3); // a4b4c4d4...
-
- // store
- _mm_storel_epi64((__m128i *) out, p0); out += out_stride;
- _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride;
- _mm_storel_epi64((__m128i *) out, p2); out += out_stride;
- _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride;
- _mm_storel_epi64((__m128i *) out, p1); out += out_stride;
- _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride;
- _mm_storel_epi64((__m128i *) out, p3); out += out_stride;
- _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e));
- }
+static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) {
+ // This is constructed to match our regular (generic) integer IDCT exactly.
+ __m128i row0, row1, row2, row3, row4, row5, row6, row7;
+ __m128i tmp;
+
+// dot product constant: even elems=x, odd elems=y
+#define dct_const(x, y) _mm_setr_epi16((x), (y), (x), (y), (x), (y), (x), (y))
+
+// out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit)
+// out(1) = c1[even]*x + c1[odd]*y
+#define dct_rot(out0, out1, x, y, c0, c1) \
+ __m128i c0##lo = _mm_unpacklo_epi16((x), (y)); \
+ __m128i c0##hi = _mm_unpackhi_epi16((x), (y)); \
+ __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \
+ __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \
+ __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \
+ __m128i out1##_h = _mm_madd_epi16(c0##hi, c1)
+
+// out = in << 12 (in 16-bit, out 32-bit)
+#define dct_widen(out, in) \
+ __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \
+ __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4)
+
+// wide add
+#define dct_wadd(out, a, b) \
+ __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \
+ __m128i out##_h = _mm_add_epi32(a##_h, b##_h)
+
+// wide sub
+#define dct_wsub(out, a, b) \
+ __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \
+ __m128i out##_h = _mm_sub_epi32(a##_h, b##_h)
+
+// butterfly a/b, add bias, then shift by "s" and pack
+#define dct_bfly32o(out0, out1, a, b, bias, s) \
+ { \
+ __m128i abiased_l = _mm_add_epi32(a##_l, bias); \
+ __m128i abiased_h = _mm_add_epi32(a##_h, bias); \
+ dct_wadd(sum, abiased, b); \
+ dct_wsub(dif, abiased, b); \
+ out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \
+ out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \
+ }
+
+// 8-bit interleave step (for transposes)
+#define dct_interleave8(a, b) \
+ tmp = a; \
+ a = _mm_unpacklo_epi8(a, b); \
+ b = _mm_unpackhi_epi8(tmp, b)
+
+// 16-bit interleave step (for transposes)
+#define dct_interleave16(a, b) \
+ tmp = a; \
+ a = _mm_unpacklo_epi16(a, b); \
+ b = _mm_unpackhi_epi16(tmp, b)
+
+#define dct_pass(bias, shift) \
+ { \
+ /* even part */ \
+ dct_rot(t2e, t3e, row2, row6, rot0_0, rot0_1); \
+ __m128i sum04 = _mm_add_epi16(row0, row4); \
+ __m128i dif04 = _mm_sub_epi16(row0, row4); \
+ dct_widen(t0e, sum04); \
+ dct_widen(t1e, dif04); \
+ dct_wadd(x0, t0e, t3e); \
+ dct_wsub(x3, t0e, t3e); \
+ dct_wadd(x1, t1e, t2e); \
+ dct_wsub(x2, t1e, t2e); \
+ /* odd part */ \
+ dct_rot(y0o, y2o, row7, row3, rot2_0, rot2_1); \
+ dct_rot(y1o, y3o, row5, row1, rot3_0, rot3_1); \
+ __m128i sum17 = _mm_add_epi16(row1, row7); \
+ __m128i sum35 = _mm_add_epi16(row3, row5); \
+ dct_rot(y4o, y5o, sum17, sum35, rot1_0, rot1_1); \
+ dct_wadd(x4, y0o, y4o); \
+ dct_wadd(x5, y1o, y5o); \
+ dct_wadd(x6, y2o, y5o); \
+ dct_wadd(x7, y3o, y4o); \
+ dct_bfly32o(row0, row7, x0, x7, bias, shift); \
+ dct_bfly32o(row1, row6, x1, x6, bias, shift); \
+ dct_bfly32o(row2, row5, x2, x5, bias, shift); \
+ dct_bfly32o(row3, row4, x3, x4, bias, shift); \
+ }
+
+ __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f));
+ __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f(0.765366865f), stbi__f2f(0.5411961f));
+ __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f));
+ __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f));
+ __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f(0.298631336f), stbi__f2f(-1.961570560f));
+ __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f(3.072711026f));
+ __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f(2.053119869f), stbi__f2f(-0.390180644f));
+ __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f(1.501321110f));
+
+ // rounding biases in column/row passes, see stbi__idct_block for explanation.
+ __m128i bias_0 = _mm_set1_epi32(512);
+ __m128i bias_1 = _mm_set1_epi32(65536 + (128 << 17));
+
+ // load
+ row0 = _mm_load_si128((const __m128i *)(data + 0 * 8));
+ row1 = _mm_load_si128((const __m128i *)(data + 1 * 8));
+ row2 = _mm_load_si128((const __m128i *)(data + 2 * 8));
+ row3 = _mm_load_si128((const __m128i *)(data + 3 * 8));
+ row4 = _mm_load_si128((const __m128i *)(data + 4 * 8));
+ row5 = _mm_load_si128((const __m128i *)(data + 5 * 8));
+ row6 = _mm_load_si128((const __m128i *)(data + 6 * 8));
+ row7 = _mm_load_si128((const __m128i *)(data + 7 * 8));
+
+ // column pass
+ dct_pass(bias_0, 10);
+
+ {
+ // 16bit 8x8 transpose pass 1
+ dct_interleave16(row0, row4);
+ dct_interleave16(row1, row5);
+ dct_interleave16(row2, row6);
+ dct_interleave16(row3, row7);
+
+ // transpose pass 2
+ dct_interleave16(row0, row2);
+ dct_interleave16(row1, row3);
+ dct_interleave16(row4, row6);
+ dct_interleave16(row5, row7);
+
+ // transpose pass 3
+ dct_interleave16(row0, row1);
+ dct_interleave16(row2, row3);
+ dct_interleave16(row4, row5);
+ dct_interleave16(row6, row7);
+ }
+
+ // row pass
+ dct_pass(bias_1, 17);
+
+ {
+ // pack
+ __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7
+ __m128i p1 = _mm_packus_epi16(row2, row3);
+ __m128i p2 = _mm_packus_epi16(row4, row5);
+ __m128i p3 = _mm_packus_epi16(row6, row7);
+
+ // 8bit 8x8 transpose pass 1
+ dct_interleave8(p0, p2); // a0e0a1e1...
+ dct_interleave8(p1, p3); // c0g0c1g1...
+
+ // transpose pass 2
+ dct_interleave8(p0, p1); // a0c0e0g0...
+ dct_interleave8(p2, p3); // b0d0f0h0...
+
+ // transpose pass 3
+ dct_interleave8(p0, p2); // a0b0c0d0...
+ dct_interleave8(p1, p3); // a4b4c4d4...
+
+ // store
+ _mm_storel_epi64((__m128i *)out, p0);
+ out += out_stride;
+ _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p0, 0x4e));
+ out += out_stride;
+ _mm_storel_epi64((__m128i *)out, p2);
+ out += out_stride;
+ _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p2, 0x4e));
+ out += out_stride;
+ _mm_storel_epi64((__m128i *)out, p1);
+ out += out_stride;
+ _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p1, 0x4e));
+ out += out_stride;
+ _mm_storel_epi64((__m128i *)out, p3);
+ out += out_stride;
+ _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p3, 0x4e));
+ }
#undef dct_const
#undef dct_rot
// NEON integer IDCT. should produce bit-identical
// results to the generic C version.
-static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
-{
- int16x8_t row0, row1, row2, row3, row4, row5, row6, row7;
-
- int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f));
- int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f));
- int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f));
- int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f));
- int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f));
- int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f));
- int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f));
- int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f));
- int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f));
- int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f));
- int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f));
- int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f));
-
-#define dct_long_mul(out, inq, coeff) \
- int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \
- int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff)
-
-#define dct_long_mac(out, acc, inq, coeff) \
- int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \
- int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff)
-
-#define dct_widen(out, inq) \
- int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \
- int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12)
+static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) {
+ int16x8_t row0, row1, row2, row3, row4, row5, row6, row7;
+
+ int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f));
+ int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f));
+ int16x4_t rot0_2 = vdup_n_s16(stbi__f2f(0.765366865f));
+ int16x4_t rot1_0 = vdup_n_s16(stbi__f2f(1.175875602f));
+ int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f));
+ int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f));
+ int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f));
+ int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f));
+ int16x4_t rot3_0 = vdup_n_s16(stbi__f2f(0.298631336f));
+ int16x4_t rot3_1 = vdup_n_s16(stbi__f2f(2.053119869f));
+ int16x4_t rot3_2 = vdup_n_s16(stbi__f2f(3.072711026f));
+ int16x4_t rot3_3 = vdup_n_s16(stbi__f2f(1.501321110f));
+
+#define dct_long_mul(out, inq, coeff) \
+ int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \
+ int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff)
+
+#define dct_long_mac(out, acc, inq, coeff) \
+ int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \
+ int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff)
+
+#define dct_widen(out, inq) \
+ int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \
+ int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12)
// wide add
-#define dct_wadd(out, a, b) \
- int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \
- int32x4_t out##_h = vaddq_s32(a##_h, b##_h)
+#define dct_wadd(out, a, b) \
+ int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \
+ int32x4_t out##_h = vaddq_s32(a##_h, b##_h)
// wide sub
-#define dct_wsub(out, a, b) \
- int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \
- int32x4_t out##_h = vsubq_s32(a##_h, b##_h)
+#define dct_wsub(out, a, b) \
+ int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \
+ int32x4_t out##_h = vsubq_s32(a##_h, b##_h)
// butterfly a/b, then shift using "shiftop" by "s" and pack
-#define dct_bfly32o(out0,out1, a,b,shiftop,s) \
- { \
- dct_wadd(sum, a, b); \
- dct_wsub(dif, a, b); \
- out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \
- out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \
- }
-
-#define dct_pass(shiftop, shift) \
- { \
- /* even part */ \
- int16x8_t sum26 = vaddq_s16(row2, row6); \
- dct_long_mul(p1e, sum26, rot0_0); \
- dct_long_mac(t2e, p1e, row6, rot0_1); \
- dct_long_mac(t3e, p1e, row2, rot0_2); \
- int16x8_t sum04 = vaddq_s16(row0, row4); \
- int16x8_t dif04 = vsubq_s16(row0, row4); \
- dct_widen(t0e, sum04); \
- dct_widen(t1e, dif04); \
- dct_wadd(x0, t0e, t3e); \
- dct_wsub(x3, t0e, t3e); \
- dct_wadd(x1, t1e, t2e); \
- dct_wsub(x2, t1e, t2e); \
- /* odd part */ \
- int16x8_t sum15 = vaddq_s16(row1, row5); \
- int16x8_t sum17 = vaddq_s16(row1, row7); \
- int16x8_t sum35 = vaddq_s16(row3, row5); \
- int16x8_t sum37 = vaddq_s16(row3, row7); \
- int16x8_t sumodd = vaddq_s16(sum17, sum35); \
- dct_long_mul(p5o, sumodd, rot1_0); \
- dct_long_mac(p1o, p5o, sum17, rot1_1); \
- dct_long_mac(p2o, p5o, sum35, rot1_2); \
- dct_long_mul(p3o, sum37, rot2_0); \
- dct_long_mul(p4o, sum15, rot2_1); \
- dct_wadd(sump13o, p1o, p3o); \
- dct_wadd(sump24o, p2o, p4o); \
- dct_wadd(sump23o, p2o, p3o); \
- dct_wadd(sump14o, p1o, p4o); \
- dct_long_mac(x4, sump13o, row7, rot3_0); \
- dct_long_mac(x5, sump24o, row5, rot3_1); \
- dct_long_mac(x6, sump23o, row3, rot3_2); \
- dct_long_mac(x7, sump14o, row1, rot3_3); \
- dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \
- dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \
- dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \
- dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \
- }
-
- // load
- row0 = vld1q_s16(data + 0*8);
- row1 = vld1q_s16(data + 1*8);
- row2 = vld1q_s16(data + 2*8);
- row3 = vld1q_s16(data + 3*8);
- row4 = vld1q_s16(data + 4*8);
- row5 = vld1q_s16(data + 5*8);
- row6 = vld1q_s16(data + 6*8);
- row7 = vld1q_s16(data + 7*8);
-
- // add DC bias
- row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0));
-
- // column pass
- dct_pass(vrshrn_n_s32, 10);
-
- // 16bit 8x8 transpose
- {
+#define dct_bfly32o(out0, out1, a, b, shiftop, s) \
+ { \
+ dct_wadd(sum, a, b); \
+ dct_wsub(dif, a, b); \
+ out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \
+ out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \
+ }
+
+#define dct_pass(shiftop, shift) \
+ { \
+ /* even part */ \
+ int16x8_t sum26 = vaddq_s16(row2, row6); \
+ dct_long_mul(p1e, sum26, rot0_0); \
+ dct_long_mac(t2e, p1e, row6, rot0_1); \
+ dct_long_mac(t3e, p1e, row2, rot0_2); \
+ int16x8_t sum04 = vaddq_s16(row0, row4); \
+ int16x8_t dif04 = vsubq_s16(row0, row4); \
+ dct_widen(t0e, sum04); \
+ dct_widen(t1e, dif04); \
+ dct_wadd(x0, t0e, t3e); \
+ dct_wsub(x3, t0e, t3e); \
+ dct_wadd(x1, t1e, t2e); \
+ dct_wsub(x2, t1e, t2e); \
+ /* odd part */ \
+ int16x8_t sum15 = vaddq_s16(row1, row5); \
+ int16x8_t sum17 = vaddq_s16(row1, row7); \
+ int16x8_t sum35 = vaddq_s16(row3, row5); \
+ int16x8_t sum37 = vaddq_s16(row3, row7); \
+ int16x8_t sumodd = vaddq_s16(sum17, sum35); \
+ dct_long_mul(p5o, sumodd, rot1_0); \
+ dct_long_mac(p1o, p5o, sum17, rot1_1); \
+ dct_long_mac(p2o, p5o, sum35, rot1_2); \
+ dct_long_mul(p3o, sum37, rot2_0); \
+ dct_long_mul(p4o, sum15, rot2_1); \
+ dct_wadd(sump13o, p1o, p3o); \
+ dct_wadd(sump24o, p2o, p4o); \
+ dct_wadd(sump23o, p2o, p3o); \
+ dct_wadd(sump14o, p1o, p4o); \
+ dct_long_mac(x4, sump13o, row7, rot3_0); \
+ dct_long_mac(x5, sump24o, row5, rot3_1); \
+ dct_long_mac(x6, sump23o, row3, rot3_2); \
+ dct_long_mac(x7, sump14o, row1, rot3_3); \
+ dct_bfly32o(row0, row7, x0, x7, shiftop, shift); \
+ dct_bfly32o(row1, row6, x1, x6, shiftop, shift); \
+ dct_bfly32o(row2, row5, x2, x5, shiftop, shift); \
+ dct_bfly32o(row3, row4, x3, x4, shiftop, shift); \
+ }
+
+ // load
+ row0 = vld1q_s16(data + 0 * 8);
+ row1 = vld1q_s16(data + 1 * 8);
+ row2 = vld1q_s16(data + 2 * 8);
+ row3 = vld1q_s16(data + 3 * 8);
+ row4 = vld1q_s16(data + 4 * 8);
+ row5 = vld1q_s16(data + 5 * 8);
+ row6 = vld1q_s16(data + 6 * 8);
+ row7 = vld1q_s16(data + 7 * 8);
+
+ // add DC bias
+ row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0));
+
+ // column pass
+ dct_pass(vrshrn_n_s32, 10);
+
+ // 16bit 8x8 transpose
+ {
// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively.
// whether compilers actually get this is another story, sadly.
-#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; }
-#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); }
-#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); }
-
- // pass 1
- dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6
- dct_trn16(row2, row3);
- dct_trn16(row4, row5);
- dct_trn16(row6, row7);
-
- // pass 2
- dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4
- dct_trn32(row1, row3);
- dct_trn32(row4, row6);
- dct_trn32(row5, row7);
-
- // pass 3
- dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0
- dct_trn64(row1, row5);
- dct_trn64(row2, row6);
- dct_trn64(row3, row7);
+#define dct_trn16(x, y) \
+ { \
+ int16x8x2_t t = vtrnq_s16(x, y); \
+ x = t.val[0]; \
+ y = t.val[1]; \
+ }
+#define dct_trn32(x, y) \
+ { \
+ int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); \
+ x = vreinterpretq_s16_s32(t.val[0]); \
+ y = vreinterpretq_s16_s32(t.val[1]); \
+ }
+#define dct_trn64(x, y) \
+ { \
+ int16x8_t x0 = x; \
+ int16x8_t y0 = y; \
+ x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); \
+ y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); \
+ }
+
+ // pass 1
+ dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6
+ dct_trn16(row2, row3);
+ dct_trn16(row4, row5);
+ dct_trn16(row6, row7);
+
+ // pass 2
+ dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4
+ dct_trn32(row1, row3);
+ dct_trn32(row4, row6);
+ dct_trn32(row5, row7);
+
+ // pass 3
+ dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0
+ dct_trn64(row1, row5);
+ dct_trn64(row2, row6);
+ dct_trn64(row3, row7);
#undef dct_trn16
#undef dct_trn32
#undef dct_trn64
- }
-
- // row pass
- // vrshrn_n_s32 only supports shifts up to 16, we need
- // 17. so do a non-rounding shift of 16 first then follow
- // up with a rounding shift by 1.
- dct_pass(vshrn_n_s32, 16);
-
- {
- // pack and round
- uint8x8_t p0 = vqrshrun_n_s16(row0, 1);
- uint8x8_t p1 = vqrshrun_n_s16(row1, 1);
- uint8x8_t p2 = vqrshrun_n_s16(row2, 1);
- uint8x8_t p3 = vqrshrun_n_s16(row3, 1);
- uint8x8_t p4 = vqrshrun_n_s16(row4, 1);
- uint8x8_t p5 = vqrshrun_n_s16(row5, 1);
- uint8x8_t p6 = vqrshrun_n_s16(row6, 1);
- uint8x8_t p7 = vqrshrun_n_s16(row7, 1);
-
- // again, these can translate into one instruction, but often don't.
-#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; }
-#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); }
-#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); }
-
- // sadly can't use interleaved stores here since we only write
- // 8 bytes to each scan line!
-
- // 8x8 8-bit transpose pass 1
- dct_trn8_8(p0, p1);
- dct_trn8_8(p2, p3);
- dct_trn8_8(p4, p5);
- dct_trn8_8(p6, p7);
-
- // pass 2
- dct_trn8_16(p0, p2);
- dct_trn8_16(p1, p3);
- dct_trn8_16(p4, p6);
- dct_trn8_16(p5, p7);
-
- // pass 3
- dct_trn8_32(p0, p4);
- dct_trn8_32(p1, p5);
- dct_trn8_32(p2, p6);
- dct_trn8_32(p3, p7);
-
- // store
- vst1_u8(out, p0); out += out_stride;
- vst1_u8(out, p1); out += out_stride;
- vst1_u8(out, p2); out += out_stride;
- vst1_u8(out, p3); out += out_stride;
- vst1_u8(out, p4); out += out_stride;
- vst1_u8(out, p5); out += out_stride;
- vst1_u8(out, p6); out += out_stride;
- vst1_u8(out, p7);
+ }
+
+ // row pass
+ // vrshrn_n_s32 only supports shifts up to 16, we need
+ // 17. so do a non-rounding shift of 16 first then follow
+ // up with a rounding shift by 1.
+ dct_pass(vshrn_n_s32, 16);
+
+ {
+ // pack and round
+ uint8x8_t p0 = vqrshrun_n_s16(row0, 1);
+ uint8x8_t p1 = vqrshrun_n_s16(row1, 1);
+ uint8x8_t p2 = vqrshrun_n_s16(row2, 1);
+ uint8x8_t p3 = vqrshrun_n_s16(row3, 1);
+ uint8x8_t p4 = vqrshrun_n_s16(row4, 1);
+ uint8x8_t p5 = vqrshrun_n_s16(row5, 1);
+ uint8x8_t p6 = vqrshrun_n_s16(row6, 1);
+ uint8x8_t p7 = vqrshrun_n_s16(row7, 1);
+
+ // again, these can translate into one instruction, but often don't.
+#define dct_trn8_8(x, y) \
+ { \
+ uint8x8x2_t t = vtrn_u8(x, y); \
+ x = t.val[0]; \
+ y = t.val[1]; \
+ }
+#define dct_trn8_16(x, y) \
+ { \
+ uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); \
+ x = vreinterpret_u8_u16(t.val[0]); \
+ y = vreinterpret_u8_u16(t.val[1]); \
+ }
+#define dct_trn8_32(x, y) \
+ { \
+ uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); \
+ x = vreinterpret_u8_u32(t.val[0]); \
+ y = vreinterpret_u8_u32(t.val[1]); \
+ }
+
+ // sadly can't use interleaved stores here since we only write
+ // 8 bytes to each scan line!
+
+ // 8x8 8-bit transpose pass 1
+ dct_trn8_8(p0, p1);
+ dct_trn8_8(p2, p3);
+ dct_trn8_8(p4, p5);
+ dct_trn8_8(p6, p7);
+
+ // pass 2
+ dct_trn8_16(p0, p2);
+ dct_trn8_16(p1, p3);
+ dct_trn8_16(p4, p6);
+ dct_trn8_16(p5, p7);
+
+ // pass 3
+ dct_trn8_32(p0, p4);
+ dct_trn8_32(p1, p5);
+ dct_trn8_32(p2, p6);
+ dct_trn8_32(p3, p7);
+
+ // store
+ vst1_u8(out, p0);
+ out += out_stride;
+ vst1_u8(out, p1);
+ out += out_stride;
+ vst1_u8(out, p2);
+ out += out_stride;
+ vst1_u8(out, p3);
+ out += out_stride;
+ vst1_u8(out, p4);
+ out += out_stride;
+ vst1_u8(out, p5);
+ out += out_stride;
+ vst1_u8(out, p6);
+ out += out_stride;
+ vst1_u8(out, p7);
#undef dct_trn8_8
#undef dct_trn8_16
#undef dct_trn8_32
- }
+ }
#undef dct_long_mul
#undef dct_long_mac
#endif // STBI_NEON
-#define STBI__MARKER_none 0xff
+#define STBI__MARKER_none 0xff
// if there's a pending marker from the entropy stream, return that
// otherwise, fetch from the stream and get a marker. if there's no
// marker, return 0xff, which is never a valid marker value
-static stbi_uc stbi__get_marker(stbi__jpeg *j)
-{
- stbi_uc x;
- if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; }
- x = stbi__get8(j->s);
- if (x != 0xff) return STBI__MARKER_none;
- while (x == 0xff)
- x = stbi__get8(j->s); // consume repeated 0xff fill bytes
- return x;
+static stbi_uc stbi__get_marker(stbi__jpeg *j) {
+ stbi_uc x;
+ if (j->marker != STBI__MARKER_none) {
+ x = j->marker;
+ j->marker = STBI__MARKER_none;
+ return x;
+ }
+ x = stbi__get8(j->s);
+ if (x != 0xff)
+ return STBI__MARKER_none;
+ while (x == 0xff)
+ x = stbi__get8(j->s); // consume repeated 0xff fill bytes
+ return x;
}
// in each scan, we'll have scan_n components, and the order
// of the components is specified by order[]
-#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7)
+#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7)
// after a restart interval, stbi__jpeg_reset the entropy decoder and
// the dc prediction
-static void stbi__jpeg_reset(stbi__jpeg *j)
-{
- j->code_bits = 0;
- j->code_buffer = 0;
- j->nomore = 0;
- j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0;
- j->marker = STBI__MARKER_none;
- j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff;
- j->eob_run = 0;
- // no more than 1<<31 MCUs if no restart_interal? that's plenty safe,
- // since we don't even allow 1<<30 pixels
-}
-
-static int stbi__parse_entropy_coded_data(stbi__jpeg *z)
-{
- stbi__jpeg_reset(z);
- if (!z->progressive) {
- if (z->scan_n == 1) {
- int i,j;
- STBI_SIMD_ALIGN(short, data[64]);
- int n = z->order[0];
- // non-interleaved data, we just need to process one block at a time,
- // in trivial scanline order
- // number of blocks to do just depends on how many actual "pixels" this
- // component has, independent of interleaved MCU blocking and such
- int w = (z->img_comp[n].x+7) >> 3;
- int h = (z->img_comp[n].y+7) >> 3;
- for (j=0; j < h; ++j) {
- for (i=0; i < w; ++i) {
- int ha = z->img_comp[n].ha;
- if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;
- z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);
- // every data block is an MCU, so countdown the restart interval
- if (--z->todo <= 0) {
- if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
- // if it's NOT a restart, then just bail, so we get corrupt data
- // rather than no data
- if (!STBI__RESTART(z->marker)) return 1;
- stbi__jpeg_reset(z);
- }
- }
- }
- return 1;
- } else { // interleaved
- int i,j,k,x,y;
- STBI_SIMD_ALIGN(short, data[64]);
- for (j=0; j < z->img_mcu_y; ++j) {
- for (i=0; i < z->img_mcu_x; ++i) {
- // scan an interleaved mcu... process scan_n components in order
- for (k=0; k < z->scan_n; ++k) {
- int n = z->order[k];
- // scan out an mcu's worth of this component; that's just determined
- // by the basic H and V specified for the component
- for (y=0; y < z->img_comp[n].v; ++y) {
- for (x=0; x < z->img_comp[n].h; ++x) {
- int x2 = (i*z->img_comp[n].h + x)*8;
- int y2 = (j*z->img_comp[n].v + y)*8;
- int ha = z->img_comp[n].ha;
- if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;
- z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data);
- }
- }
- }
- // after all interleaved components, that's an interleaved MCU,
- // so now count down the restart interval
- if (--z->todo <= 0) {
- if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
- if (!STBI__RESTART(z->marker)) return 1;
- stbi__jpeg_reset(z);
- }
- }
- }
- return 1;
- }
- } else {
- if (z->scan_n == 1) {
- int i,j;
- int n = z->order[0];
- // non-interleaved data, we just need to process one block at a time,
- // in trivial scanline order
- // number of blocks to do just depends on how many actual "pixels" this
- // component has, independent of interleaved MCU blocking and such
- int w = (z->img_comp[n].x+7) >> 3;
- int h = (z->img_comp[n].y+7) >> 3;
- for (j=0; j < h; ++j) {
- for (i=0; i < w; ++i) {
- short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
- if (z->spec_start == 0) {
- if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
- return 0;
- } else {
- int ha = z->img_comp[n].ha;
- if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha]))
- return 0;
- }
- // every data block is an MCU, so countdown the restart interval
- if (--z->todo <= 0) {
- if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
- if (!STBI__RESTART(z->marker)) return 1;
- stbi__jpeg_reset(z);
- }
- }
- }
- return 1;
- } else { // interleaved
- int i,j,k,x,y;
- for (j=0; j < z->img_mcu_y; ++j) {
- for (i=0; i < z->img_mcu_x; ++i) {
- // scan an interleaved mcu... process scan_n components in order
- for (k=0; k < z->scan_n; ++k) {
- int n = z->order[k];
- // scan out an mcu's worth of this component; that's just determined
- // by the basic H and V specified for the component
- for (y=0; y < z->img_comp[n].v; ++y) {
- for (x=0; x < z->img_comp[n].h; ++x) {
- int x2 = (i*z->img_comp[n].h + x);
- int y2 = (j*z->img_comp[n].v + y);
- short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w);
- if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
- return 0;
- }
- }
- }
- // after all interleaved components, that's an interleaved MCU,
- // so now count down the restart interval
- if (--z->todo <= 0) {
- if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
- if (!STBI__RESTART(z->marker)) return 1;
- stbi__jpeg_reset(z);
- }
- }
- }
- return 1;
- }
- }
-}
-
-static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant)
-{
- int i;
- for (i=0; i < 64; ++i)
- data[i] *= dequant[i];
-}
-
-static void stbi__jpeg_finish(stbi__jpeg *z)
-{
- if (z->progressive) {
- // dequantize and idct the data
- int i,j,n;
- for (n=0; n < z->s->img_n; ++n) {
- int w = (z->img_comp[n].x+7) >> 3;
- int h = (z->img_comp[n].y+7) >> 3;
- for (j=0; j < h; ++j) {
- for (i=0; i < w; ++i) {
- short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
- stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]);
- z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);
- }
- }
- }
- }
-}
-
-static int stbi__process_marker(stbi__jpeg *z, int m)
-{
- int L;
- switch (m) {
- case STBI__MARKER_none: // no marker found
- return stbi__err("expected marker","Corrupt JPEG");
-
- case 0xDD: // DRI - specify restart interval
- if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG");
- z->restart_interval = stbi__get16be(z->s);
- return 1;
-
- case 0xDB: // DQT - define quantization table
- L = stbi__get16be(z->s)-2;
- while (L > 0) {
- int q = stbi__get8(z->s);
- int p = q >> 4, sixteen = (p != 0);
- int t = q & 15,i;
- if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG");
- if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG");
-
- for (i=0; i < 64; ++i)
- z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s));
- L -= (sixteen ? 129 : 65);
- }
- return L==0;
-
- case 0xC4: // DHT - define huffman table
- L = stbi__get16be(z->s)-2;
- while (L > 0) {
- stbi_uc *v;
- int sizes[16],i,n=0;
- int q = stbi__get8(z->s);
- int tc = q >> 4;
- int th = q & 15;
- if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG");
- for (i=0; i < 16; ++i) {
- sizes[i] = stbi__get8(z->s);
- n += sizes[i];
- }
- L -= 17;
- if (tc == 0) {
- if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0;
- v = z->huff_dc[th].values;
- } else {
- if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0;
- v = z->huff_ac[th].values;
- }
- for (i=0; i < n; ++i)
- v[i] = stbi__get8(z->s);
- if (tc != 0)
- stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th);
- L -= n;
- }
- return L==0;
- }
-
- // check for comment block or APP blocks
- if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) {
- L = stbi__get16be(z->s);
- if (L < 2) {
- if (m == 0xFE)
- return stbi__err("bad COM len","Corrupt JPEG");
- else
- return stbi__err("bad APP len","Corrupt JPEG");
- }
- L -= 2;
-
- if (m == 0xE0 && L >= 5) { // JFIF APP0 segment
- static const unsigned char tag[5] = {'J','F','I','F','\0'};
- int ok = 1;
- int i;
- for (i=0; i < 5; ++i)
- if (stbi__get8(z->s) != tag[i])
- ok = 0;
- L -= 5;
- if (ok)
- z->jfif = 1;
- } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment
- static const unsigned char tag[6] = {'A','d','o','b','e','\0'};
- int ok = 1;
- int i;
- for (i=0; i < 6; ++i)
- if (stbi__get8(z->s) != tag[i])
- ok = 0;
- L -= 6;
- if (ok) {
- stbi__get8(z->s); // version
- stbi__get16be(z->s); // flags0
- stbi__get16be(z->s); // flags1
- z->app14_color_transform = stbi__get8(z->s); // color transform
- L -= 6;
- }
- }
-
- stbi__skip(z->s, L);
- return 1;
- }
-
- return stbi__err("unknown marker","Corrupt JPEG");
+static void stbi__jpeg_reset(stbi__jpeg *j) {
+ j->code_bits = 0;
+ j->code_buffer = 0;
+ j->nomore = 0;
+ j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0;
+ j->marker = STBI__MARKER_none;
+ j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff;
+ j->eob_run = 0;
+ // no more than 1<<31 MCUs if no restart_interal? that's plenty safe,
+ // since we don't even allow 1<<30 pixels
+}
+
+static int stbi__parse_entropy_coded_data(stbi__jpeg *z) {
+ stbi__jpeg_reset(z);
+ if (!z->progressive) {
+ if (z->scan_n == 1) {
+ int i, j;
+ STBI_SIMD_ALIGN(short, data[64]);
+ int n = z->order[0];
+ // non-interleaved data, we just need to process one block at a time,
+ // in trivial scanline order
+ // number of blocks to do just depends on how many actual "pixels" this
+ // component has, independent of interleaved MCU blocking and such
+ int w = (z->img_comp[n].x + 7) >> 3;
+ int h = (z->img_comp[n].y + 7) >> 3;
+ for (j = 0; j < h; ++j) {
+ for (i = 0; i < w; ++i) {
+ int ha = z->img_comp[n].ha;
+ if (!stbi__jpeg_decode_block(z, data, z->huff_dc + z->img_comp[n].hd, z->huff_ac + ha,
+ z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq]))
+ return 0;
+ z->idct_block_kernel(z->img_comp[n].data + z->img_comp[n].w2 * j * 8 + i * 8, z->img_comp[n].w2,
+ data);
+ // every data block is an MCU, so countdown the restart interval
+ if (--z->todo <= 0) {
+ if (z->code_bits < 24)
+ stbi__grow_buffer_unsafe(z);
+ // if it's NOT a restart, then just bail, so we get corrupt data
+ // rather than no data
+ if (!STBI__RESTART(z->marker))
+ return 1;
+ stbi__jpeg_reset(z);
+ }
+ }
+ }
+ return 1;
+ } else { // interleaved
+ int i, j, k, x, y;
+ STBI_SIMD_ALIGN(short, data[64]);
+ for (j = 0; j < z->img_mcu_y; ++j) {
+ for (i = 0; i < z->img_mcu_x; ++i) {
+ // scan an interleaved mcu... process scan_n components in order
+ for (k = 0; k < z->scan_n; ++k) {
+ int n = z->order[k];
+ // scan out an mcu's worth of this component; that's just determined
+ // by the basic H and V specified for the component
+ for (y = 0; y < z->img_comp[n].v; ++y) {
+ for (x = 0; x < z->img_comp[n].h; ++x) {
+ int x2 = (i * z->img_comp[n].h + x) * 8;
+ int y2 = (j * z->img_comp[n].v + y) * 8;
+ int ha = z->img_comp[n].ha;
+ if (!stbi__jpeg_decode_block(z, data, z->huff_dc + z->img_comp[n].hd, z->huff_ac + ha,
+ z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq]))
+ return 0;
+ z->idct_block_kernel(z->img_comp[n].data + z->img_comp[n].w2 * y2 + x2,
+ z->img_comp[n].w2, data);
+ }
+ }
+ }
+ // after all interleaved components, that's an interleaved MCU,
+ // so now count down the restart interval
+ if (--z->todo <= 0) {
+ if (z->code_bits < 24)
+ stbi__grow_buffer_unsafe(z);
+ if (!STBI__RESTART(z->marker))
+ return 1;
+ stbi__jpeg_reset(z);
+ }
+ }
+ }
+ return 1;
+ }
+ } else {
+ if (z->scan_n == 1) {
+ int i, j;
+ int n = z->order[0];
+ // non-interleaved data, we just need to process one block at a time,
+ // in trivial scanline order
+ // number of blocks to do just depends on how many actual "pixels" this
+ // component has, independent of interleaved MCU blocking and such
+ int w = (z->img_comp[n].x + 7) >> 3;
+ int h = (z->img_comp[n].y + 7) >> 3;
+ for (j = 0; j < h; ++j) {
+ for (i = 0; i < w; ++i) {
+ short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
+ if (z->spec_start == 0) {
+ if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
+ return 0;
+ } else {
+ int ha = z->img_comp[n].ha;
+ if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha]))
+ return 0;
+ }
+ // every data block is an MCU, so countdown the restart interval
+ if (--z->todo <= 0) {
+ if (z->code_bits < 24)
+ stbi__grow_buffer_unsafe(z);
+ if (!STBI__RESTART(z->marker))
+ return 1;
+ stbi__jpeg_reset(z);
+ }
+ }
+ }
+ return 1;
+ } else { // interleaved
+ int i, j, k, x, y;
+ for (j = 0; j < z->img_mcu_y; ++j) {
+ for (i = 0; i < z->img_mcu_x; ++i) {
+ // scan an interleaved mcu... process scan_n components in order
+ for (k = 0; k < z->scan_n; ++k) {
+ int n = z->order[k];
+ // scan out an mcu's worth of this component; that's just determined
+ // by the basic H and V specified for the component
+ for (y = 0; y < z->img_comp[n].v; ++y) {
+ for (x = 0; x < z->img_comp[n].h; ++x) {
+ int x2 = (i * z->img_comp[n].h + x);
+ int y2 = (j * z->img_comp[n].v + y);
+ short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w);
+ if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
+ return 0;
+ }
+ }
+ }
+ // after all interleaved components, that's an interleaved MCU,
+ // so now count down the restart interval
+ if (--z->todo <= 0) {
+ if (z->code_bits < 24)
+ stbi__grow_buffer_unsafe(z);
+ if (!STBI__RESTART(z->marker))
+ return 1;
+ stbi__jpeg_reset(z);
+ }
+ }
+ }
+ return 1;
+ }
+ }
+}
+
+static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) {
+ int i;
+ for (i = 0; i < 64; ++i)
+ data[i] *= dequant[i];
+}
+
+static void stbi__jpeg_finish(stbi__jpeg *z) {
+ if (z->progressive) {
+ // dequantize and idct the data
+ int i, j, n;
+ for (n = 0; n < z->s->img_n; ++n) {
+ int w = (z->img_comp[n].x + 7) >> 3;
+ int h = (z->img_comp[n].y + 7) >> 3;
+ for (j = 0; j < h; ++j) {
+ for (i = 0; i < w; ++i) {
+ short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
+ stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]);
+ z->idct_block_kernel(z->img_comp[n].data + z->img_comp[n].w2 * j * 8 + i * 8, z->img_comp[n].w2,
+ data);
+ }
+ }
+ }
+ }
+}
+
+static int stbi__process_marker(stbi__jpeg *z, int m) {
+ int L;
+ switch (m) {
+ case STBI__MARKER_none: // no marker found
+ return stbi__err("expected marker", "Corrupt JPEG");
+
+ case 0xDD: // DRI - specify restart interval
+ if (stbi__get16be(z->s) != 4)
+ return stbi__err("bad DRI len", "Corrupt JPEG");
+ z->restart_interval = stbi__get16be(z->s);
+ return 1;
+
+ case 0xDB: // DQT - define quantization table
+ L = stbi__get16be(z->s) - 2;
+ while (L > 0) {
+ int q = stbi__get8(z->s);
+ int p = q >> 4, sixteen = (p != 0);
+ int t = q & 15, i;
+ if (p != 0 && p != 1)
+ return stbi__err("bad DQT type", "Corrupt JPEG");
+ if (t > 3)
+ return stbi__err("bad DQT table", "Corrupt JPEG");
+
+ for (i = 0; i < 64; ++i)
+ z->dequant[t][stbi__jpeg_dezigzag[i]] =
+ (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s));
+ L -= (sixteen ? 129 : 65);
+ }
+ return L == 0;
+
+ case 0xC4: // DHT - define huffman table
+ L = stbi__get16be(z->s) - 2;
+ while (L > 0) {
+ stbi_uc *v;
+ int sizes[16], i, n = 0;
+ int q = stbi__get8(z->s);
+ int tc = q >> 4;
+ int th = q & 15;
+ if (tc > 1 || th > 3)
+ return stbi__err("bad DHT header", "Corrupt JPEG");
+ for (i = 0; i < 16; ++i) {
+ sizes[i] = stbi__get8(z->s);
+ n += sizes[i];
+ }
+ L -= 17;
+ if (tc == 0) {
+ if (!stbi__build_huffman(z->huff_dc + th, sizes))
+ return 0;
+ v = z->huff_dc[th].values;
+ } else {
+ if (!stbi__build_huffman(z->huff_ac + th, sizes))
+ return 0;
+ v = z->huff_ac[th].values;
+ }
+ for (i = 0; i < n; ++i)
+ v[i] = stbi__get8(z->s);
+ if (tc != 0)
+ stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th);
+ L -= n;
+ }
+ return L == 0;
+ }
+
+ // check for comment block or APP blocks
+ if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) {
+ L = stbi__get16be(z->s);
+ if (L < 2) {
+ if (m == 0xFE)
+ return stbi__err("bad COM len", "Corrupt JPEG");
+ else
+ return stbi__err("bad APP len", "Corrupt JPEG");
+ }
+ L -= 2;
+
+ if (m == 0xE0 && L >= 5) { // JFIF APP0 segment
+ static const unsigned char tag[5] = {'J', 'F', 'I', 'F', '\0'};
+ int ok = 1;
+ int i;
+ for (i = 0; i < 5; ++i)
+ if (stbi__get8(z->s) != tag[i])
+ ok = 0;
+ L -= 5;
+ if (ok)
+ z->jfif = 1;
+ } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment
+ static const unsigned char tag[6] = {'A', 'd', 'o', 'b', 'e', '\0'};
+ int ok = 1;
+ int i;
+ for (i = 0; i < 6; ++i)
+ if (stbi__get8(z->s) != tag[i])
+ ok = 0;
+ L -= 6;
+ if (ok) {
+ stbi__get8(z->s); // version
+ stbi__get16be(z->s); // flags0
+ stbi__get16be(z->s); // flags1
+ z->app14_color_transform = stbi__get8(z->s); // color transform
+ L -= 6;
+ }
+ }
+
+ stbi__skip(z->s, L);
+ return 1;
+ }
+
+ return stbi__err("unknown marker", "Corrupt JPEG");
}
// after we see SOS
-static int stbi__process_scan_header(stbi__jpeg *z)
-{
- int i;
- int Ls = stbi__get16be(z->s);
- z->scan_n = stbi__get8(z->s);
- if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG");
- if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG");
- for (i=0; i < z->scan_n; ++i) {
- int id = stbi__get8(z->s), which;
- int q = stbi__get8(z->s);
- for (which = 0; which < z->s->img_n; ++which)
- if (z->img_comp[which].id == id)
- break;
- if (which == z->s->img_n) return 0; // no match
- z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG");
- z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG");
- z->order[i] = which;
- }
-
- {
- int aa;
- z->spec_start = stbi__get8(z->s);
- z->spec_end = stbi__get8(z->s); // should be 63, but might be 0
- aa = stbi__get8(z->s);
- z->succ_high = (aa >> 4);
- z->succ_low = (aa & 15);
- if (z->progressive) {
- if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13)
- return stbi__err("bad SOS", "Corrupt JPEG");
- } else {
- if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG");
- if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG");
- z->spec_end = 63;
- }
- }
-
- return 1;
-}
-
-static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why)
-{
- int i;
- for (i=0; i < ncomp; ++i) {
- if (z->img_comp[i].raw_data) {
- STBI_FREE(z->img_comp[i].raw_data);
- z->img_comp[i].raw_data = NULL;
- z->img_comp[i].data = NULL;
- }
- if (z->img_comp[i].raw_coeff) {
- STBI_FREE(z->img_comp[i].raw_coeff);
- z->img_comp[i].raw_coeff = 0;
- z->img_comp[i].coeff = 0;
- }
- if (z->img_comp[i].linebuf) {
- STBI_FREE(z->img_comp[i].linebuf);
- z->img_comp[i].linebuf = NULL;
- }
- }
- return why;
-}
-
-static int stbi__process_frame_header(stbi__jpeg *z, int scan)
-{
- stbi__context *s = z->s;
- int Lf,p,i,q, h_max=1,v_max=1,c;
- Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG
- p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline
- s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
- s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires
- c = stbi__get8(s);
- if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG");
- s->img_n = c;
- for (i=0; i < c; ++i) {
- z->img_comp[i].data = NULL;
- z->img_comp[i].linebuf = NULL;
- }
-
- if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");
-
- z->rgb = 0;
- for (i=0; i < s->img_n; ++i) {
- static const unsigned char rgb[3] = { 'R', 'G', 'B' };
- z->img_comp[i].id = stbi__get8(s);
- if (s->img_n == 3 && z->img_comp[i].id == rgb[i])
- ++z->rgb;
- q = stbi__get8(s);
- z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");
- z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");
- z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG");
- }
-
- if (scan != STBI__SCAN_load) return 1;
-
- if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode");
-
- for (i=0; i < s->img_n; ++i) {
- if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h;
- if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v;
- }
-
- // compute interleaved mcu info
- z->img_h_max = h_max;
- z->img_v_max = v_max;
- z->img_mcu_w = h_max * 8;
- z->img_mcu_h = v_max * 8;
- // these sizes can't be more than 17 bits
- z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w;
- z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
-
- for (i=0; i < s->img_n; ++i) {
- // number of effective pixels (e.g. for non-interleaved MCU)
- z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max;
- z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max;
- // to simplify generation, we'll allocate enough memory to decode
- // the bogus oversized data from using interleaved MCUs and their
- // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
- // discard the extra data until colorspace conversion
- //
- // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier)
- // so these muls can't overflow with 32-bit ints (which we require)
- z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;
- z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
- z->img_comp[i].coeff = 0;
- z->img_comp[i].raw_coeff = 0;
- z->img_comp[i].linebuf = NULL;
- z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15);
- if (z->img_comp[i].raw_data == NULL)
- return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
- // align blocks for idct using mmx/sse
- z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15);
- if (z->progressive) {
- // w2, h2 are multiples of 8 (see above)
- z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8;
- z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8;
- z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15);
- if (z->img_comp[i].raw_coeff == NULL)
- return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
- z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15);
- }
- }
-
- return 1;
+static int stbi__process_scan_header(stbi__jpeg *z) {
+ int i;
+ int Ls = stbi__get16be(z->s);
+ z->scan_n = stbi__get8(z->s);
+ if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int)z->s->img_n)
+ return stbi__err("bad SOS component count", "Corrupt JPEG");
+ if (Ls != 6 + 2 * z->scan_n)
+ return stbi__err("bad SOS len", "Corrupt JPEG");
+ for (i = 0; i < z->scan_n; ++i) {
+ int id = stbi__get8(z->s), which;
+ int q = stbi__get8(z->s);
+ for (which = 0; which < z->s->img_n; ++which)
+ if (z->img_comp[which].id == id)
+ break;
+ if (which == z->s->img_n)
+ return 0; // no match
+ z->img_comp[which].hd = q >> 4;
+ if (z->img_comp[which].hd > 3)
+ return stbi__err("bad DC huff", "Corrupt JPEG");
+ z->img_comp[which].ha = q & 15;
+ if (z->img_comp[which].ha > 3)
+ return stbi__err("bad AC huff", "Corrupt JPEG");
+ z->order[i] = which;
+ }
+
+ {
+ int aa;
+ z->spec_start = stbi__get8(z->s);
+ z->spec_end = stbi__get8(z->s); // should be 63, but might be 0
+ aa = stbi__get8(z->s);
+ z->succ_high = (aa >> 4);
+ z->succ_low = (aa & 15);
+ if (z->progressive) {
+ if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 ||
+ z->succ_low > 13)
+ return stbi__err("bad SOS", "Corrupt JPEG");
+ } else {
+ if (z->spec_start != 0)
+ return stbi__err("bad SOS", "Corrupt JPEG");
+ if (z->succ_high != 0 || z->succ_low != 0)
+ return stbi__err("bad SOS", "Corrupt JPEG");
+ z->spec_end = 63;
+ }
+ }
+
+ return 1;
+}
+
+static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) {
+ int i;
+ for (i = 0; i < ncomp; ++i) {
+ if (z->img_comp[i].raw_data) {
+ STBI_FREE(z->img_comp[i].raw_data);
+ z->img_comp[i].raw_data = NULL;
+ z->img_comp[i].data = NULL;
+ }
+ if (z->img_comp[i].raw_coeff) {
+ STBI_FREE(z->img_comp[i].raw_coeff);
+ z->img_comp[i].raw_coeff = 0;
+ z->img_comp[i].coeff = 0;
+ }
+ if (z->img_comp[i].linebuf) {
+ STBI_FREE(z->img_comp[i].linebuf);
+ z->img_comp[i].linebuf = NULL;
+ }
+ }
+ return why;
+}
+
+static int stbi__process_frame_header(stbi__jpeg *z, int scan) {
+ stbi__context *s = z->s;
+ int Lf, p, i, q, h_max = 1, v_max = 1, c;
+ Lf = stbi__get16be(s);
+ if (Lf < 11)
+ return stbi__err("bad SOF len", "Corrupt JPEG"); // JPEG
+ p = stbi__get8(s);
+ if (p != 8)
+ return stbi__err("only 8-bit", "JPEG format not supported: 8-bit only"); // JPEG baseline
+ s->img_y = stbi__get16be(s);
+ if (s->img_y == 0)
+ return stbi__err(
+ "no header height",
+ "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
+ s->img_x = stbi__get16be(s);
+ if (s->img_x == 0)
+ return stbi__err("0 width", "Corrupt JPEG"); // JPEG requires
+ c = stbi__get8(s);
+ if (c != 3 && c != 1 && c != 4)
+ return stbi__err("bad component count", "Corrupt JPEG");
+ s->img_n = c;
+ for (i = 0; i < c; ++i) {
+ z->img_comp[i].data = NULL;
+ z->img_comp[i].linebuf = NULL;
+ }
+
+ if (Lf != 8 + 3 * s->img_n)
+ return stbi__err("bad SOF len", "Corrupt JPEG");
+
+ z->rgb = 0;
+ for (i = 0; i < s->img_n; ++i) {
+ static const unsigned char rgb[3] = {'R', 'G', 'B'};
+ z->img_comp[i].id = stbi__get8(s);
+ if (s->img_n == 3 && z->img_comp[i].id == rgb[i])
+ ++z->rgb;
+ q = stbi__get8(s);
+ z->img_comp[i].h = (q >> 4);
+ if (!z->img_comp[i].h || z->img_comp[i].h > 4)
+ return stbi__err("bad H", "Corrupt JPEG");
+ z->img_comp[i].v = q & 15;
+ if (!z->img_comp[i].v || z->img_comp[i].v > 4)
+ return stbi__err("bad V", "Corrupt JPEG");
+ z->img_comp[i].tq = stbi__get8(s);
+ if (z->img_comp[i].tq > 3)
+ return stbi__err("bad TQ", "Corrupt JPEG");
+ }
+
+ if (scan != STBI__SCAN_load)
+ return 1;
+
+ if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0))
+ return stbi__err("too large", "Image too large to decode");
+
+ for (i = 0; i < s->img_n; ++i) {
+ if (z->img_comp[i].h > h_max)
+ h_max = z->img_comp[i].h;
+ if (z->img_comp[i].v > v_max)
+ v_max = z->img_comp[i].v;
+ }
+
+ // compute interleaved mcu info
+ z->img_h_max = h_max;
+ z->img_v_max = v_max;
+ z->img_mcu_w = h_max * 8;
+ z->img_mcu_h = v_max * 8;
+ // these sizes can't be more than 17 bits
+ z->img_mcu_x = (s->img_x + z->img_mcu_w - 1) / z->img_mcu_w;
+ z->img_mcu_y = (s->img_y + z->img_mcu_h - 1) / z->img_mcu_h;
+
+ for (i = 0; i < s->img_n; ++i) {
+ // number of effective pixels (e.g. for non-interleaved MCU)
+ z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max - 1) / h_max;
+ z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max - 1) / v_max;
+ // to simplify generation, we'll allocate enough memory to decode
+ // the bogus oversized data from using interleaved MCUs and their
+ // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
+ // discard the extra data until colorspace conversion
+ //
+ // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier)
+ // so these muls can't overflow with 32-bit ints (which we require)
+ z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;
+ z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
+ z->img_comp[i].coeff = 0;
+ z->img_comp[i].raw_coeff = 0;
+ z->img_comp[i].linebuf = NULL;
+ z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15);
+ if (z->img_comp[i].raw_data == NULL)
+ return stbi__free_jpeg_components(z, i + 1, stbi__err("outofmem", "Out of memory"));
+ // align blocks for idct using mmx/sse
+ z->img_comp[i].data = (stbi_uc *)(((size_t)z->img_comp[i].raw_data + 15) & ~15);
+ if (z->progressive) {
+ // w2, h2 are multiples of 8 (see above)
+ z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8;
+ z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8;
+ z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15);
+ if (z->img_comp[i].raw_coeff == NULL)
+ return stbi__free_jpeg_components(z, i + 1, stbi__err("outofmem", "Out of memory"));
+ z->img_comp[i].coeff = (short *)(((size_t)z->img_comp[i].raw_coeff + 15) & ~15);
+ }
+ }
+
+ return 1;
}
// use comparisons since in some cases we handle more than one case (e.g. SOF)
-#define stbi__DNL(x) ((x) == 0xdc)
-#define stbi__SOI(x) ((x) == 0xd8)
-#define stbi__EOI(x) ((x) == 0xd9)
-#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2)
-#define stbi__SOS(x) ((x) == 0xda)
-
-#define stbi__SOF_progressive(x) ((x) == 0xc2)
-
-static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
-{
- int m;
- z->jfif = 0;
- z->app14_color_transform = -1; // valid values are 0,1,2
- z->marker = STBI__MARKER_none; // initialize cached marker to empty
- m = stbi__get_marker(z);
- if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG");
- if (scan == STBI__SCAN_type) return 1;
- m = stbi__get_marker(z);
- while (!stbi__SOF(m)) {
- if (!stbi__process_marker(z,m)) return 0;
- m = stbi__get_marker(z);
- while (m == STBI__MARKER_none) {
- // some files have extra padding after their blocks, so ok, we'll scan
- if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG");
- m = stbi__get_marker(z);
- }
- }
- z->progressive = stbi__SOF_progressive(m);
- if (!stbi__process_frame_header(z, scan)) return 0;
- return 1;
+#define stbi__DNL(x) ((x) == 0xdc)
+#define stbi__SOI(x) ((x) == 0xd8)
+#define stbi__EOI(x) ((x) == 0xd9)
+#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2)
+#define stbi__SOS(x) ((x) == 0xda)
+
+#define stbi__SOF_progressive(x) ((x) == 0xc2)
+
+static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) {
+ int m;
+ z->jfif = 0;
+ z->app14_color_transform = -1; // valid values are 0,1,2
+ z->marker = STBI__MARKER_none; // initialize cached marker to empty
+ m = stbi__get_marker(z);
+ if (!stbi__SOI(m))
+ return stbi__err("no SOI", "Corrupt JPEG");
+ if (scan == STBI__SCAN_type)
+ return 1;
+ m = stbi__get_marker(z);
+ while (!stbi__SOF(m)) {
+ if (!stbi__process_marker(z, m))
+ return 0;
+ m = stbi__get_marker(z);
+ while (m == STBI__MARKER_none) {
+ // some files have extra padding after their blocks, so ok, we'll scan
+ if (stbi__at_eof(z->s))
+ return stbi__err("no SOF", "Corrupt JPEG");
+ m = stbi__get_marker(z);
+ }
+ }
+ z->progressive = stbi__SOF_progressive(m);
+ if (!stbi__process_frame_header(z, scan))
+ return 0;
+ return 1;
}
// decode image to YCbCr format
-static int stbi__decode_jpeg_image(stbi__jpeg *j)
-{
- int m;
- for (m = 0; m < 4; m++) {
- j->img_comp[m].raw_data = NULL;
- j->img_comp[m].raw_coeff = NULL;
- }
- j->restart_interval = 0;
- if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0;
- m = stbi__get_marker(j);
- while (!stbi__EOI(m)) {
- if (stbi__SOS(m)) {
- if (!stbi__process_scan_header(j)) return 0;
- if (!stbi__parse_entropy_coded_data(j)) return 0;
- if (j->marker == STBI__MARKER_none ) {
- // handle 0s at the end of image data from IP Kamera 9060
- while (!stbi__at_eof(j->s)) {
- int x = stbi__get8(j->s);
- if (x == 255) {
- j->marker = stbi__get8(j->s);
- break;
- }
- }
- // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0
- }
- } else if (stbi__DNL(m)) {
- int Ld = stbi__get16be(j->s);
- stbi__uint32 NL = stbi__get16be(j->s);
- if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG");
- if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG");
- } else {
- if (!stbi__process_marker(j, m)) return 0;
- }
- m = stbi__get_marker(j);
- }
- if (j->progressive)
- stbi__jpeg_finish(j);
- return 1;
+static int stbi__decode_jpeg_image(stbi__jpeg *j) {
+ int m;
+ for (m = 0; m < 4; m++) {
+ j->img_comp[m].raw_data = NULL;
+ j->img_comp[m].raw_coeff = NULL;
+ }
+ j->restart_interval = 0;
+ if (!stbi__decode_jpeg_header(j, STBI__SCAN_load))
+ return 0;
+ m = stbi__get_marker(j);
+ while (!stbi__EOI(m)) {
+ if (stbi__SOS(m)) {
+ if (!stbi__process_scan_header(j))
+ return 0;
+ if (!stbi__parse_entropy_coded_data(j))
+ return 0;
+ if (j->marker == STBI__MARKER_none) {
+ // handle 0s at the end of image data from IP Kamera 9060
+ while (!stbi__at_eof(j->s)) {
+ int x = stbi__get8(j->s);
+ if (x == 255) {
+ j->marker = stbi__get8(j->s);
+ break;
+ }
+ }
+ // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually
+ // return 0
+ }
+ } else if (stbi__DNL(m)) {
+ int Ld = stbi__get16be(j->s);
+ stbi__uint32 NL = stbi__get16be(j->s);
+ if (Ld != 4)
+ return stbi__err("bad DNL len", "Corrupt JPEG");
+ if (NL != j->s->img_y)
+ return stbi__err("bad DNL height", "Corrupt JPEG");
+ } else {
+ if (!stbi__process_marker(j, m))
+ return 0;
+ }
+ m = stbi__get_marker(j);
+ }
+ if (j->progressive)
+ stbi__jpeg_finish(j);
+ return 1;
}
// static jfif-centered resampling (across block boundaries)
-typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1,
- int w, int hs);
+typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, int w, int hs);
-#define stbi__div4(x) ((stbi_uc) ((x) >> 2))
+#define stbi__div4(x) ((stbi_uc)((x) >> 2))
-static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
-{
- STBI_NOTUSED(out);
- STBI_NOTUSED(in_far);
- STBI_NOTUSED(w);
- STBI_NOTUSED(hs);
- return in_near;
+static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) {
+ STBI_NOTUSED(out);
+ STBI_NOTUSED(in_far);
+ STBI_NOTUSED(w);
+ STBI_NOTUSED(hs);
+ return in_near;
}
-static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
-{
- // need to generate two samples vertically for every one in input
- int i;
- STBI_NOTUSED(hs);
- for (i=0; i < w; ++i)
- out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2);
- return out;
+static stbi_uc *stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) {
+ // need to generate two samples vertically for every one in input
+ int i;
+ STBI_NOTUSED(hs);
+ for (i = 0; i < w; ++i)
+ out[i] = stbi__div4(3 * in_near[i] + in_far[i] + 2);
+ return out;
}
-static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
-{
- // need to generate two samples horizontally for every one in input
- int i;
- stbi_uc *input = in_near;
+static stbi_uc *stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) {
+ // need to generate two samples horizontally for every one in input
+ int i;
+ stbi_uc *input = in_near;
- if (w == 1) {
- // if only one sample, can't do any interpolation
- out[0] = out[1] = input[0];
- return out;
- }
+ if (w == 1) {
+ // if only one sample, can't do any interpolation
+ out[0] = out[1] = input[0];
+ return out;
+ }
- out[0] = input[0];
- out[1] = stbi__div4(input[0]*3 + input[1] + 2);
- for (i=1; i < w-1; ++i) {
- int n = 3*input[i]+2;
- out[i*2+0] = stbi__div4(n+input[i-1]);
- out[i*2+1] = stbi__div4(n+input[i+1]);
- }
- out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2);
- out[i*2+1] = input[w-1];
+ out[0] = input[0];
+ out[1] = stbi__div4(input[0] * 3 + input[1] + 2);
+ for (i = 1; i < w - 1; ++i) {
+ int n = 3 * input[i] + 2;
+ out[i * 2 + 0] = stbi__div4(n + input[i - 1]);
+ out[i * 2 + 1] = stbi__div4(n + input[i + 1]);
+ }
+ out[i * 2 + 0] = stbi__div4(input[w - 2] * 3 + input[w - 1] + 2);
+ out[i * 2 + 1] = input[w - 1];
- STBI_NOTUSED(in_far);
- STBI_NOTUSED(hs);
+ STBI_NOTUSED(in_far);
+ STBI_NOTUSED(hs);
- return out;
+ return out;
}
-#define stbi__div16(x) ((stbi_uc) ((x) >> 4))
+#define stbi__div16(x) ((stbi_uc)((x) >> 4))
-static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
-{
- // need to generate 2x2 samples for every one in input
- int i,t0,t1;
- if (w == 1) {
- out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);
- return out;
- }
+static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) {
+ // need to generate 2x2 samples for every one in input
+ int i, t0, t1;
+ if (w == 1) {
+ out[0] = out[1] = stbi__div4(3 * in_near[0] + in_far[0] + 2);
+ return out;
+ }
- t1 = 3*in_near[0] + in_far[0];
- out[0] = stbi__div4(t1+2);
- for (i=1; i < w; ++i) {
- t0 = t1;
- t1 = 3*in_near[i]+in_far[i];
- out[i*2-1] = stbi__div16(3*t0 + t1 + 8);
- out[i*2 ] = stbi__div16(3*t1 + t0 + 8);
- }
- out[w*2-1] = stbi__div4(t1+2);
+ t1 = 3 * in_near[0] + in_far[0];
+ out[0] = stbi__div4(t1 + 2);
+ for (i = 1; i < w; ++i) {
+ t0 = t1;
+ t1 = 3 * in_near[i] + in_far[i];
+ out[i * 2 - 1] = stbi__div16(3 * t0 + t1 + 8);
+ out[i * 2] = stbi__div16(3 * t1 + t0 + 8);
+ }
+ out[w * 2 - 1] = stbi__div4(t1 + 2);
- STBI_NOTUSED(hs);
+ STBI_NOTUSED(hs);
- return out;
+ return out;
}
#if defined(STBI_SSE2) || defined(STBI_NEON)
-static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
-{
- // need to generate 2x2 samples for every one in input
- int i=0,t0,t1;
-
- if (w == 1) {
- out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);
- return out;
- }
-
- t1 = 3*in_near[0] + in_far[0];
- // process groups of 8 pixels for as long as we can.
- // note we can't handle the last pixel in a row in this loop
- // because we need to handle the filter boundary conditions.
- for (; i < ((w-1) & ~7); i += 8) {
+static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) {
+ // need to generate 2x2 samples for every one in input
+ int i = 0, t0, t1;
+
+ if (w == 1) {
+ out[0] = out[1] = stbi__div4(3 * in_near[0] + in_far[0] + 2);
+ return out;
+ }
+
+ t1 = 3 * in_near[0] + in_far[0];
+ // process groups of 8 pixels for as long as we can.
+ // note we can't handle the last pixel in a row in this loop
+ // because we need to handle the filter boundary conditions.
+ for (; i < ((w - 1) & ~7); i += 8) {
#if defined(STBI_SSE2)
- // load and perform the vertical filtering pass
- // this uses 3*x + y = 4*x + (y - x)
- __m128i zero = _mm_setzero_si128();
- __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i));
- __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i));
- __m128i farw = _mm_unpacklo_epi8(farb, zero);
- __m128i nearw = _mm_unpacklo_epi8(nearb, zero);
- __m128i diff = _mm_sub_epi16(farw, nearw);
- __m128i nears = _mm_slli_epi16(nearw, 2);
- __m128i curr = _mm_add_epi16(nears, diff); // current row
-
- // horizontal filter works the same based on shifted vers of current
- // row. "prev" is current row shifted right by 1 pixel; we need to
- // insert the previous pixel value (from t1).
- // "next" is current row shifted left by 1 pixel, with first pixel
- // of next block of 8 pixels added in.
- __m128i prv0 = _mm_slli_si128(curr, 2);
- __m128i nxt0 = _mm_srli_si128(curr, 2);
- __m128i prev = _mm_insert_epi16(prv0, t1, 0);
- __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7);
-
- // horizontal filter, polyphase implementation since it's convenient:
- // even pixels = 3*cur + prev = cur*4 + (prev - cur)
- // odd pixels = 3*cur + next = cur*4 + (next - cur)
- // note the shared term.
- __m128i bias = _mm_set1_epi16(8);
- __m128i curs = _mm_slli_epi16(curr, 2);
- __m128i prvd = _mm_sub_epi16(prev, curr);
- __m128i nxtd = _mm_sub_epi16(next, curr);
- __m128i curb = _mm_add_epi16(curs, bias);
- __m128i even = _mm_add_epi16(prvd, curb);
- __m128i odd = _mm_add_epi16(nxtd, curb);
-
- // interleave even and odd pixels, then undo scaling.
- __m128i int0 = _mm_unpacklo_epi16(even, odd);
- __m128i int1 = _mm_unpackhi_epi16(even, odd);
- __m128i de0 = _mm_srli_epi16(int0, 4);
- __m128i de1 = _mm_srli_epi16(int1, 4);
-
- // pack and write output
- __m128i outv = _mm_packus_epi16(de0, de1);
- _mm_storeu_si128((__m128i *) (out + i*2), outv);
+ // load and perform the vertical filtering pass
+ // this uses 3*x + y = 4*x + (y - x)
+ __m128i zero = _mm_setzero_si128();
+ __m128i farb = _mm_loadl_epi64((__m128i *)(in_far + i));
+ __m128i nearb = _mm_loadl_epi64((__m128i *)(in_near + i));
+ __m128i farw = _mm_unpacklo_epi8(farb, zero);
+ __m128i nearw = _mm_unpacklo_epi8(nearb, zero);
+ __m128i diff = _mm_sub_epi16(farw, nearw);
+ __m128i nears = _mm_slli_epi16(nearw, 2);
+ __m128i curr = _mm_add_epi16(nears, diff); // current row
+
+ // horizontal filter works the same based on shifted vers of current
+ // row. "prev" is current row shifted right by 1 pixel; we need to
+ // insert the previous pixel value (from t1).
+ // "next" is current row shifted left by 1 pixel, with first pixel
+ // of next block of 8 pixels added in.
+ __m128i prv0 = _mm_slli_si128(curr, 2);
+ __m128i nxt0 = _mm_srli_si128(curr, 2);
+ __m128i prev = _mm_insert_epi16(prv0, t1, 0);
+ __m128i next = _mm_insert_epi16(nxt0, 3 * in_near[i + 8] + in_far[i + 8], 7);
+
+ // horizontal filter, polyphase implementation since it's convenient:
+ // even pixels = 3*cur + prev = cur*4 + (prev - cur)
+ // odd pixels = 3*cur + next = cur*4 + (next - cur)
+ // note the shared term.
+ __m128i bias = _mm_set1_epi16(8);
+ __m128i curs = _mm_slli_epi16(curr, 2);
+ __m128i prvd = _mm_sub_epi16(prev, curr);
+ __m128i nxtd = _mm_sub_epi16(next, curr);
+ __m128i curb = _mm_add_epi16(curs, bias);
+ __m128i even = _mm_add_epi16(prvd, curb);
+ __m128i odd = _mm_add_epi16(nxtd, curb);
+
+ // interleave even and odd pixels, then undo scaling.
+ __m128i int0 = _mm_unpacklo_epi16(even, odd);
+ __m128i int1 = _mm_unpackhi_epi16(even, odd);
+ __m128i de0 = _mm_srli_epi16(int0, 4);
+ __m128i de1 = _mm_srli_epi16(int1, 4);
+
+ // pack and write output
+ __m128i outv = _mm_packus_epi16(de0, de1);
+ _mm_storeu_si128((__m128i *)(out + i * 2), outv);
#elif defined(STBI_NEON)
- // load and perform the vertical filtering pass
- // this uses 3*x + y = 4*x + (y - x)
- uint8x8_t farb = vld1_u8(in_far + i);
- uint8x8_t nearb = vld1_u8(in_near + i);
- int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb));
- int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2));
- int16x8_t curr = vaddq_s16(nears, diff); // current row
-
- // horizontal filter works the same based on shifted vers of current
- // row. "prev" is current row shifted right by 1 pixel; we need to
- // insert the previous pixel value (from t1).
- // "next" is current row shifted left by 1 pixel, with first pixel
- // of next block of 8 pixels added in.
- int16x8_t prv0 = vextq_s16(curr, curr, 7);
- int16x8_t nxt0 = vextq_s16(curr, curr, 1);
- int16x8_t prev = vsetq_lane_s16(t1, prv0, 0);
- int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7);
-
- // horizontal filter, polyphase implementation since it's convenient:
- // even pixels = 3*cur + prev = cur*4 + (prev - cur)
- // odd pixels = 3*cur + next = cur*4 + (next - cur)
- // note the shared term.
- int16x8_t curs = vshlq_n_s16(curr, 2);
- int16x8_t prvd = vsubq_s16(prev, curr);
- int16x8_t nxtd = vsubq_s16(next, curr);
- int16x8_t even = vaddq_s16(curs, prvd);
- int16x8_t odd = vaddq_s16(curs, nxtd);
-
- // undo scaling and round, then store with even/odd phases interleaved
- uint8x8x2_t o;
- o.val[0] = vqrshrun_n_s16(even, 4);
- o.val[1] = vqrshrun_n_s16(odd, 4);
- vst2_u8(out + i*2, o);
+ // load and perform the vertical filtering pass
+ // this uses 3*x + y = 4*x + (y - x)
+ uint8x8_t farb = vld1_u8(in_far + i);
+ uint8x8_t nearb = vld1_u8(in_near + i);
+ int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb));
+ int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2));
+ int16x8_t curr = vaddq_s16(nears, diff); // current row
+
+ // horizontal filter works the same based on shifted vers of current
+ // row. "prev" is current row shifted right by 1 pixel; we need to
+ // insert the previous pixel value (from t1).
+ // "next" is current row shifted left by 1 pixel, with first pixel
+ // of next block of 8 pixels added in.
+ int16x8_t prv0 = vextq_s16(curr, curr, 7);
+ int16x8_t nxt0 = vextq_s16(curr, curr, 1);
+ int16x8_t prev = vsetq_lane_s16(t1, prv0, 0);
+ int16x8_t next = vsetq_lane_s16(3 * in_near[i + 8] + in_far[i + 8], nxt0, 7);
+
+ // horizontal filter, polyphase implementation since it's convenient:
+ // even pixels = 3*cur + prev = cur*4 + (prev - cur)
+ // odd pixels = 3*cur + next = cur*4 + (next - cur)
+ // note the shared term.
+ int16x8_t curs = vshlq_n_s16(curr, 2);
+ int16x8_t prvd = vsubq_s16(prev, curr);
+ int16x8_t nxtd = vsubq_s16(next, curr);
+ int16x8_t even = vaddq_s16(curs, prvd);
+ int16x8_t odd = vaddq_s16(curs, nxtd);
+
+ // undo scaling and round, then store with even/odd phases interleaved
+ uint8x8x2_t o;
+ o.val[0] = vqrshrun_n_s16(even, 4);
+ o.val[1] = vqrshrun_n_s16(odd, 4);
+ vst2_u8(out + i * 2, o);
#endif
- // "previous" value for next iter
- t1 = 3*in_near[i+7] + in_far[i+7];
- }
+ // "previous" value for next iter
+ t1 = 3 * in_near[i + 7] + in_far[i + 7];
+ }
- t0 = t1;
- t1 = 3*in_near[i] + in_far[i];
- out[i*2] = stbi__div16(3*t1 + t0 + 8);
+ t0 = t1;
+ t1 = 3 * in_near[i] + in_far[i];
+ out[i * 2] = stbi__div16(3 * t1 + t0 + 8);
- for (++i; i < w; ++i) {
- t0 = t1;
- t1 = 3*in_near[i]+in_far[i];
- out[i*2-1] = stbi__div16(3*t0 + t1 + 8);
- out[i*2 ] = stbi__div16(3*t1 + t0 + 8);
- }
- out[w*2-1] = stbi__div4(t1+2);
+ for (++i; i < w; ++i) {
+ t0 = t1;
+ t1 = 3 * in_near[i] + in_far[i];
+ out[i * 2 - 1] = stbi__div16(3 * t0 + t1 + 8);
+ out[i * 2] = stbi__div16(3 * t1 + t0 + 8);
+ }
+ out[w * 2 - 1] = stbi__div4(t1 + 2);
- STBI_NOTUSED(hs);
+ STBI_NOTUSED(hs);
- return out;
+ return out;
}
#endif
-static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
-{
- // resample with nearest-neighbor
- int i,j;
- STBI_NOTUSED(in_far);
- for (i=0; i < w; ++i)
- for (j=0; j < hs; ++j)
- out[i*hs+j] = in_near[i];
- return out;
+static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) {
+ // resample with nearest-neighbor
+ int i, j;
+ STBI_NOTUSED(in_far);
+ for (i = 0; i < w; ++i)
+ for (j = 0; j < hs; ++j)
+ out[i * hs + j] = in_near[i];
+ return out;
}
// this is a reduced-precision calculation of YCbCr-to-RGB introduced
// to make sure the code produces the same results in both SIMD and scalar
-#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8)
-static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step)
-{
- int i;
- for (i=0; i < count; ++i) {
- int y_fixed = (y[i] << 20) + (1<<19); // rounding
- int r,g,b;
- int cr = pcr[i] - 128;
- int cb = pcb[i] - 128;
- r = y_fixed + cr* stbi__float2fixed(1.40200f);
- g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
- b = y_fixed + cb* stbi__float2fixed(1.77200f);
- r >>= 20;
- g >>= 20;
- b >>= 20;
- if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
- if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
- if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
- out[0] = (stbi_uc)r;
- out[1] = (stbi_uc)g;
- out[2] = (stbi_uc)b;
- out[3] = 255;
- out += step;
- }
+#define stbi__float2fixed(x) (((int)((x)*4096.0f + 0.5f)) << 8)
+static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count,
+ int step) {
+ int i;
+ for (i = 0; i < count; ++i) {
+ int y_fixed = (y[i] << 20) + (1 << 19); // rounding
+ int r, g, b;
+ int cr = pcr[i] - 128;
+ int cb = pcb[i] - 128;
+ r = y_fixed + cr * stbi__float2fixed(1.40200f);
+ g = y_fixed + (cr * -stbi__float2fixed(0.71414f)) + ((cb * -stbi__float2fixed(0.34414f)) & 0xffff0000);
+ b = y_fixed + cb * stbi__float2fixed(1.77200f);
+ r >>= 20;
+ g >>= 20;
+ b >>= 20;
+ if ((unsigned)r > 255) {
+ if (r < 0)
+ r = 0;
+ else
+ r = 255;
+ }
+ if ((unsigned)g > 255) {
+ if (g < 0)
+ g = 0;
+ else
+ g = 255;
+ }
+ if ((unsigned)b > 255) {
+ if (b < 0)
+ b = 0;
+ else
+ b = 255;
+ }
+ out[0] = (stbi_uc)r;
+ out[1] = (stbi_uc)g;
+ out[2] = (stbi_uc)b;
+ out[3] = 255;
+ out += step;
+ }
}
#if defined(STBI_SSE2) || defined(STBI_NEON)
-static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step)
-{
- int i = 0;
+static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count,
+ int step) {
+ int i = 0;
#ifdef STBI_SSE2
- // step == 3 is pretty ugly on the final interleave, and i'm not convinced
- // it's useful in practice (you wouldn't use it for textures, for example).
- // so just accelerate step == 4 case.
- if (step == 4) {
- // this is a fairly straightforward implementation and not super-optimized.
- __m128i signflip = _mm_set1_epi8(-0x80);
- __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f));
- __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f));
- __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f));
- __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f));
- __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128);
- __m128i xw = _mm_set1_epi16(255); // alpha channel
-
- for (; i+7 < count; i += 8) {
- // load
- __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i));
- __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i));
- __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i));
- __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128
- __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128
-
- // unpack to short (and left-shift cr, cb by 8)
- __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes);
- __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased);
- __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased);
-
- // color transform
- __m128i yws = _mm_srli_epi16(yw, 4);
- __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw);
- __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw);
- __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1);
- __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1);
- __m128i rws = _mm_add_epi16(cr0, yws);
- __m128i gwt = _mm_add_epi16(cb0, yws);
- __m128i bws = _mm_add_epi16(yws, cb1);
- __m128i gws = _mm_add_epi16(gwt, cr1);
-
- // descale
- __m128i rw = _mm_srai_epi16(rws, 4);
- __m128i bw = _mm_srai_epi16(bws, 4);
- __m128i gw = _mm_srai_epi16(gws, 4);
-
- // back to byte, set up for transpose
- __m128i brb = _mm_packus_epi16(rw, bw);
- __m128i gxb = _mm_packus_epi16(gw, xw);
-
- // transpose to interleave channels
- __m128i t0 = _mm_unpacklo_epi8(brb, gxb);
- __m128i t1 = _mm_unpackhi_epi8(brb, gxb);
- __m128i o0 = _mm_unpacklo_epi16(t0, t1);
- __m128i o1 = _mm_unpackhi_epi16(t0, t1);
-
- // store
- _mm_storeu_si128((__m128i *) (out + 0), o0);
- _mm_storeu_si128((__m128i *) (out + 16), o1);
- out += 32;
- }
- }
+ // step == 3 is pretty ugly on the final interleave, and i'm not convinced
+ // it's useful in practice (you wouldn't use it for textures, for example).
+ // so just accelerate step == 4 case.
+ if (step == 4) {
+ // this is a fairly straightforward implementation and not super-optimized.
+ __m128i signflip = _mm_set1_epi8(-0x80);
+ __m128i cr_const0 = _mm_set1_epi16((short)(1.40200f * 4096.0f + 0.5f));
+ __m128i cr_const1 = _mm_set1_epi16(-(short)(0.71414f * 4096.0f + 0.5f));
+ __m128i cb_const0 = _mm_set1_epi16(-(short)(0.34414f * 4096.0f + 0.5f));
+ __m128i cb_const1 = _mm_set1_epi16((short)(1.77200f * 4096.0f + 0.5f));
+ __m128i y_bias = _mm_set1_epi8((char)(unsigned char)128);
+ __m128i xw = _mm_set1_epi16(255); // alpha channel
+
+ for (; i + 7 < count; i += 8) {
+ // load
+ __m128i y_bytes = _mm_loadl_epi64((__m128i *)(y + i));
+ __m128i cr_bytes = _mm_loadl_epi64((__m128i *)(pcr + i));
+ __m128i cb_bytes = _mm_loadl_epi64((__m128i *)(pcb + i));
+ __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128
+ __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128
+
+ // unpack to short (and left-shift cr, cb by 8)
+ __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes);
+ __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased);
+ __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased);
+
+ // color transform
+ __m128i yws = _mm_srli_epi16(yw, 4);
+ __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw);
+ __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw);
+ __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1);
+ __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1);
+ __m128i rws = _mm_add_epi16(cr0, yws);
+ __m128i gwt = _mm_add_epi16(cb0, yws);
+ __m128i bws = _mm_add_epi16(yws, cb1);
+ __m128i gws = _mm_add_epi16(gwt, cr1);
+
+ // descale
+ __m128i rw = _mm_srai_epi16(rws, 4);
+ __m128i bw = _mm_srai_epi16(bws, 4);
+ __m128i gw = _mm_srai_epi16(gws, 4);
+
+ // back to byte, set up for transpose
+ __m128i brb = _mm_packus_epi16(rw, bw);
+ __m128i gxb = _mm_packus_epi16(gw, xw);
+
+ // transpose to interleave channels
+ __m128i t0 = _mm_unpacklo_epi8(brb, gxb);
+ __m128i t1 = _mm_unpackhi_epi8(brb, gxb);
+ __m128i o0 = _mm_unpacklo_epi16(t0, t1);
+ __m128i o1 = _mm_unpackhi_epi16(t0, t1);
+
+ // store
+ _mm_storeu_si128((__m128i *)(out + 0), o0);
+ _mm_storeu_si128((__m128i *)(out + 16), o1);
+ out += 32;
+ }
+ }
#endif
#ifdef STBI_NEON
- // in this version, step=3 support would be easy to add. but is there demand?
- if (step == 4) {
- // this is a fairly straightforward implementation and not super-optimized.
- uint8x8_t signflip = vdup_n_u8(0x80);
- int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f));
- int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f));
- int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f));
- int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f));
-
- for (; i+7 < count; i += 8) {
- // load
- uint8x8_t y_bytes = vld1_u8(y + i);
- uint8x8_t cr_bytes = vld1_u8(pcr + i);
- uint8x8_t cb_bytes = vld1_u8(pcb + i);
- int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip));
- int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip));
-
- // expand to s16
- int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4));
- int16x8_t crw = vshll_n_s8(cr_biased, 7);
- int16x8_t cbw = vshll_n_s8(cb_biased, 7);
-
- // color transform
- int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0);
- int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0);
- int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1);
- int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1);
- int16x8_t rws = vaddq_s16(yws, cr0);
- int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1);
- int16x8_t bws = vaddq_s16(yws, cb1);
-
- // undo scaling, round, convert to byte
- uint8x8x4_t o;
- o.val[0] = vqrshrun_n_s16(rws, 4);
- o.val[1] = vqrshrun_n_s16(gws, 4);
- o.val[2] = vqrshrun_n_s16(bws, 4);
- o.val[3] = vdup_n_u8(255);
-
- // store, interleaving r/g/b/a
- vst4_u8(out, o);
- out += 8*4;
- }
- }
+ // in this version, step=3 support would be easy to add. but is there demand?
+ if (step == 4) {
+ // this is a fairly straightforward implementation and not super-optimized.
+ uint8x8_t signflip = vdup_n_u8(0x80);
+ int16x8_t cr_const0 = vdupq_n_s16((short)(1.40200f * 4096.0f + 0.5f));
+ int16x8_t cr_const1 = vdupq_n_s16(-(short)(0.71414f * 4096.0f + 0.5f));
+ int16x8_t cb_const0 = vdupq_n_s16(-(short)(0.34414f * 4096.0f + 0.5f));
+ int16x8_t cb_const1 = vdupq_n_s16((short)(1.77200f * 4096.0f + 0.5f));
+
+ for (; i + 7 < count; i += 8) {
+ // load
+ uint8x8_t y_bytes = vld1_u8(y + i);
+ uint8x8_t cr_bytes = vld1_u8(pcr + i);
+ uint8x8_t cb_bytes = vld1_u8(pcb + i);
+ int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip));
+ int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip));
+
+ // expand to s16
+ int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4));
+ int16x8_t crw = vshll_n_s8(cr_biased, 7);
+ int16x8_t cbw = vshll_n_s8(cb_biased, 7);
+
+ // color transform
+ int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0);
+ int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0);
+ int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1);
+ int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1);
+ int16x8_t rws = vaddq_s16(yws, cr0);
+ int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1);
+ int16x8_t bws = vaddq_s16(yws, cb1);
+
+ // undo scaling, round, convert to byte
+ uint8x8x4_t o;
+ o.val[0] = vqrshrun_n_s16(rws, 4);
+ o.val[1] = vqrshrun_n_s16(gws, 4);
+ o.val[2] = vqrshrun_n_s16(bws, 4);
+ o.val[3] = vdup_n_u8(255);
+
+ // store, interleaving r/g/b/a
+ vst4_u8(out, o);
+ out += 8 * 4;
+ }
+ }
#endif
- for (; i < count; ++i) {
- int y_fixed = (y[i] << 20) + (1<<19); // rounding
- int r,g,b;
- int cr = pcr[i] - 128;
- int cb = pcb[i] - 128;
- r = y_fixed + cr* stbi__float2fixed(1.40200f);
- g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
- b = y_fixed + cb* stbi__float2fixed(1.77200f);
- r >>= 20;
- g >>= 20;
- b >>= 20;
- if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
- if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
- if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
- out[0] = (stbi_uc)r;
- out[1] = (stbi_uc)g;
- out[2] = (stbi_uc)b;
- out[3] = 255;
- out += step;
- }
+ for (; i < count; ++i) {
+ int y_fixed = (y[i] << 20) + (1 << 19); // rounding
+ int r, g, b;
+ int cr = pcr[i] - 128;
+ int cb = pcb[i] - 128;
+ r = y_fixed + cr * stbi__float2fixed(1.40200f);
+ g = y_fixed + cr * -stbi__float2fixed(0.71414f) + ((cb * -stbi__float2fixed(0.34414f)) & 0xffff0000);
+ b = y_fixed + cb * stbi__float2fixed(1.77200f);
+ r >>= 20;
+ g >>= 20;
+ b >>= 20;
+ if ((unsigned)r > 255) {
+ if (r < 0)
+ r = 0;
+ else
+ r = 255;
+ }
+ if ((unsigned)g > 255) {
+ if (g < 0)
+ g = 0;
+ else
+ g = 255;
+ }
+ if ((unsigned)b > 255) {
+ if (b < 0)
+ b = 0;
+ else
+ b = 255;
+ }
+ out[0] = (stbi_uc)r;
+ out[1] = (stbi_uc)g;
+ out[2] = (stbi_uc)b;
+ out[3] = 255;
+ out += step;
+ }
}
#endif
// set up the kernels
-static void stbi__setup_jpeg(stbi__jpeg *j)
-{
- j->idct_block_kernel = stbi__idct_block;
- j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row;
- j->resample_row_hv_2_kernel = stbi__resample_row_hv_2;
+static void stbi__setup_jpeg(stbi__jpeg *j) {
+ j->idct_block_kernel = stbi__idct_block;
+ j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row;
+ j->resample_row_hv_2_kernel = stbi__resample_row_hv_2;
#ifdef STBI_SSE2
- if (stbi__sse2_available()) {
- j->idct_block_kernel = stbi__idct_simd;
- j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
- j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
- }
+ if (stbi__sse2_available()) {
+ j->idct_block_kernel = stbi__idct_simd;
+ j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
+ j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
+ }
#endif
#ifdef STBI_NEON
- j->idct_block_kernel = stbi__idct_simd;
- j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
- j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
+ j->idct_block_kernel = stbi__idct_simd;
+ j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
+ j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
#endif
}
// clean up the temporary component buffers
-static void stbi__cleanup_jpeg(stbi__jpeg *j)
-{
- stbi__free_jpeg_components(j, j->s->img_n, 0);
-}
-
-typedef struct
-{
- resample_row_func resample;
- stbi_uc *line0,*line1;
- int hs,vs; // expansion factor in each axis
- int w_lores; // horizontal pixels pre-expansion
- int ystep; // how far through vertical expansion we are
- int ypos; // which pre-expansion row we're on
+static void stbi__cleanup_jpeg(stbi__jpeg *j) { stbi__free_jpeg_components(j, j->s->img_n, 0); }
+
+typedef struct {
+ resample_row_func resample;
+ stbi_uc *line0, *line1;
+ int hs, vs; // expansion factor in each axis
+ int w_lores; // horizontal pixels pre-expansion
+ int ystep; // how far through vertical expansion we are
+ int ypos; // which pre-expansion row we're on
} stbi__resample;
// fast 0..255 * 0..255 => 0..255 rounded multiplication
-static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y)
-{
- unsigned int t = x*y + 128;
- return (stbi_uc) ((t + (t >>8)) >> 8);
-}
-
-static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp)
-{
- int n, decode_n, is_rgb;
- z->s->img_n = 0; // make stbi__cleanup_jpeg safe
-
- // validate req_comp
- if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
-
- // load a jpeg image from whichever source, but leave in YCbCr format
- if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; }
-
- // determine actual number of components to generate
- n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1;
-
- is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif));
-
- if (z->s->img_n == 3 && n < 3 && !is_rgb)
- decode_n = 1;
- else
- decode_n = z->s->img_n;
-
- // resample and color-convert
- {
- int k;
- unsigned int i,j;
- stbi_uc *output;
- stbi_uc *coutput[4];
-
- stbi__resample res_comp[4];
-
- for (k=0; k < decode_n; ++k) {
- stbi__resample *r = &res_comp[k];
-
- // allocate line buffer big enough for upsampling off the edges
- // with upsample factor of 4
- z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3);
- if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
-
- r->hs = z->img_h_max / z->img_comp[k].h;
- r->vs = z->img_v_max / z->img_comp[k].v;
- r->ystep = r->vs >> 1;
- r->w_lores = (z->s->img_x + r->hs-1) / r->hs;
- r->ypos = 0;
- r->line0 = r->line1 = z->img_comp[k].data;
-
- if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1;
- else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2;
- else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2;
- else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel;
- else r->resample = stbi__resample_row_generic;
- }
-
- // can't error after this so, this is safe
- output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1);
- if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
-
- // now go ahead and resample
- for (j=0; j < z->s->img_y; ++j) {
- stbi_uc *out = output + n * z->s->img_x * j;
- for (k=0; k < decode_n; ++k) {
- stbi__resample *r = &res_comp[k];
- int y_bot = r->ystep >= (r->vs >> 1);
- coutput[k] = r->resample(z->img_comp[k].linebuf,
- y_bot ? r->line1 : r->line0,
- y_bot ? r->line0 : r->line1,
- r->w_lores, r->hs);
- if (++r->ystep >= r->vs) {
- r->ystep = 0;
- r->line0 = r->line1;
- if (++r->ypos < z->img_comp[k].y)
- r->line1 += z->img_comp[k].w2;
- }
- }
- if (n >= 3) {
- stbi_uc *y = coutput[0];
- if (z->s->img_n == 3) {
- if (is_rgb) {
- for (i=0; i < z->s->img_x; ++i) {
- out[0] = y[i];
- out[1] = coutput[1][i];
- out[2] = coutput[2][i];
- out[3] = 255;
- out += n;
- }
- } else {
- z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
- }
- } else if (z->s->img_n == 4) {
- if (z->app14_color_transform == 0) { // CMYK
- for (i=0; i < z->s->img_x; ++i) {
- stbi_uc m = coutput[3][i];
- out[0] = stbi__blinn_8x8(coutput[0][i], m);
- out[1] = stbi__blinn_8x8(coutput[1][i], m);
- out[2] = stbi__blinn_8x8(coutput[2][i], m);
- out[3] = 255;
- out += n;
- }
- } else if (z->app14_color_transform == 2) { // YCCK
- z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
- for (i=0; i < z->s->img_x; ++i) {
- stbi_uc m = coutput[3][i];
- out[0] = stbi__blinn_8x8(255 - out[0], m);
- out[1] = stbi__blinn_8x8(255 - out[1], m);
- out[2] = stbi__blinn_8x8(255 - out[2], m);
- out += n;
- }
- } else { // YCbCr + alpha? Ignore the fourth channel for now
- z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
- }
- } else
- for (i=0; i < z->s->img_x; ++i) {
- out[0] = out[1] = out[2] = y[i];
- out[3] = 255; // not used if n==3
- out += n;
- }
- } else {
- if (is_rgb) {
- if (n == 1)
- for (i=0; i < z->s->img_x; ++i)
- *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
- else {
- for (i=0; i < z->s->img_x; ++i, out += 2) {
- out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
- out[1] = 255;
- }
- }
- } else if (z->s->img_n == 4 && z->app14_color_transform == 0) {
- for (i=0; i < z->s->img_x; ++i) {
- stbi_uc m = coutput[3][i];
- stbi_uc r = stbi__blinn_8x8(coutput[0][i], m);
- stbi_uc g = stbi__blinn_8x8(coutput[1][i], m);
- stbi_uc b = stbi__blinn_8x8(coutput[2][i], m);
- out[0] = stbi__compute_y(r, g, b);
- out[1] = 255;
- out += n;
- }
- } else if (z->s->img_n == 4 && z->app14_color_transform == 2) {
- for (i=0; i < z->s->img_x; ++i) {
- out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]);
- out[1] = 255;
- out += n;
- }
- } else {
- stbi_uc *y = coutput[0];
- if (n == 1)
- for (i=0; i < z->s->img_x; ++i) out[i] = y[i];
- else
- for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255;
- }
- }
- }
- stbi__cleanup_jpeg(z);
- *out_x = z->s->img_x;
- *out_y = z->s->img_y;
- if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output
- return output;
- }
-}
-
-static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
-{
- unsigned char* result;
- stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
- STBI_NOTUSED(ri);
- j->s = s;
- stbi__setup_jpeg(j);
- result = load_jpeg_image(j, x,y,comp,req_comp);
- STBI_FREE(j);
- return result;
-}
-
-static int stbi__jpeg_test(stbi__context *s)
-{
- int r;
- stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
- j->s = s;
- stbi__setup_jpeg(j);
- r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
- stbi__rewind(s);
- STBI_FREE(j);
- return r;
-}
-
-static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp)
-{
- if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) {
- stbi__rewind( j->s );
- return 0;
- }
- if (x) *x = j->s->img_x;
- if (y) *y = j->s->img_y;
- if (comp) *comp = j->s->img_n >= 3 ? 3 : 1;
- return 1;
-}
-
-static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
-{
- int result;
- stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
- j->s = s;
- result = stbi__jpeg_info_raw(j, x, y, comp);
- STBI_FREE(j);
- return result;
+static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) {
+ unsigned int t = x * y + 128;
+ return (stbi_uc)((t + (t >> 8)) >> 8);
+}
+
+static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) {
+ int n, decode_n, is_rgb;
+ z->s->img_n = 0; // make stbi__cleanup_jpeg safe
+
+ // validate req_comp
+ if (req_comp < 0 || req_comp > 4)
+ return stbi__errpuc("bad req_comp", "Internal error");
+
+ // load a jpeg image from whichever source, but leave in YCbCr format
+ if (!stbi__decode_jpeg_image(z)) {
+ stbi__cleanup_jpeg(z);
+ return NULL;
+ }
+
+ // determine actual number of components to generate
+ n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1;
+
+ is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif));
+
+ if (z->s->img_n == 3 && n < 3 && !is_rgb)
+ decode_n = 1;
+ else
+ decode_n = z->s->img_n;
+
+ // resample and color-convert
+ {
+ int k;
+ unsigned int i, j;
+ stbi_uc *output;
+ stbi_uc *coutput[4];
+
+ stbi__resample res_comp[4];
+
+ for (k = 0; k < decode_n; ++k) {
+ stbi__resample *r = &res_comp[k];
+
+ // allocate line buffer big enough for upsampling off the edges
+ // with upsample factor of 4
+ z->img_comp[k].linebuf = (stbi_uc *)stbi__malloc(z->s->img_x + 3);
+ if (!z->img_comp[k].linebuf) {
+ stbi__cleanup_jpeg(z);
+ return stbi__errpuc("outofmem", "Out of memory");
+ }
+
+ r->hs = z->img_h_max / z->img_comp[k].h;
+ r->vs = z->img_v_max / z->img_comp[k].v;
+ r->ystep = r->vs >> 1;
+ r->w_lores = (z->s->img_x + r->hs - 1) / r->hs;
+ r->ypos = 0;
+ r->line0 = r->line1 = z->img_comp[k].data;
+
+ if (r->hs == 1 && r->vs == 1)
+ r->resample = resample_row_1;
+ else if (r->hs == 1 && r->vs == 2)
+ r->resample = stbi__resample_row_v_2;
+ else if (r->hs == 2 && r->vs == 1)
+ r->resample = stbi__resample_row_h_2;
+ else if (r->hs == 2 && r->vs == 2)
+ r->resample = z->resample_row_hv_2_kernel;
+ else
+ r->resample = stbi__resample_row_generic;
+ }
+
+ // can't error after this so, this is safe
+ output = (stbi_uc *)stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1);
+ if (!output) {
+ stbi__cleanup_jpeg(z);
+ return stbi__errpuc("outofmem", "Out of memory");
+ }
+
+ // now go ahead and resample
+ for (j = 0; j < z->s->img_y; ++j) {
+ stbi_uc *out = output + n * z->s->img_x * j;
+ for (k = 0; k < decode_n; ++k) {
+ stbi__resample *r = &res_comp[k];
+ int y_bot = r->ystep >= (r->vs >> 1);
+ coutput[k] = r->resample(z->img_comp[k].linebuf, y_bot ? r->line1 : r->line0,
+ y_bot ? r->line0 : r->line1, r->w_lores, r->hs);
+ if (++r->ystep >= r->vs) {
+ r->ystep = 0;
+ r->line0 = r->line1;
+ if (++r->ypos < z->img_comp[k].y)
+ r->line1 += z->img_comp[k].w2;
+ }
+ }
+ if (n >= 3) {
+ stbi_uc *y = coutput[0];
+ if (z->s->img_n == 3) {
+ if (is_rgb) {
+ for (i = 0; i < z->s->img_x; ++i) {
+ out[0] = y[i];
+ out[1] = coutput[1][i];
+ out[2] = coutput[2][i];
+ out[3] = 255;
+ out += n;
+ }
+ } else {
+ z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+ }
+ } else if (z->s->img_n == 4) {
+ if (z->app14_color_transform == 0) { // CMYK
+ for (i = 0; i < z->s->img_x; ++i) {
+ stbi_uc m = coutput[3][i];
+ out[0] = stbi__blinn_8x8(coutput[0][i], m);
+ out[1] = stbi__blinn_8x8(coutput[1][i], m);
+ out[2] = stbi__blinn_8x8(coutput[2][i], m);
+ out[3] = 255;
+ out += n;
+ }
+ } else if (z->app14_color_transform == 2) { // YCCK
+ z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+ for (i = 0; i < z->s->img_x; ++i) {
+ stbi_uc m = coutput[3][i];
+ out[0] = stbi__blinn_8x8(255 - out[0], m);
+ out[1] = stbi__blinn_8x8(255 - out[1], m);
+ out[2] = stbi__blinn_8x8(255 - out[2], m);
+ out += n;
+ }
+ } else { // YCbCr + alpha? Ignore the fourth channel for now
+ z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+ }
+ } else
+ for (i = 0; i < z->s->img_x; ++i) {
+ out[0] = out[1] = out[2] = y[i];
+ out[3] = 255; // not used if n==3
+ out += n;
+ }
+ } else {
+ if (is_rgb) {
+ if (n == 1)
+ for (i = 0; i < z->s->img_x; ++i)
+ *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
+ else {
+ for (i = 0; i < z->s->img_x; ++i, out += 2) {
+ out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
+ out[1] = 255;
+ }
+ }
+ } else if (z->s->img_n == 4 && z->app14_color_transform == 0) {
+ for (i = 0; i < z->s->img_x; ++i) {
+ stbi_uc m = coutput[3][i];
+ stbi_uc r = stbi__blinn_8x8(coutput[0][i], m);
+ stbi_uc g = stbi__blinn_8x8(coutput[1][i], m);
+ stbi_uc b = stbi__blinn_8x8(coutput[2][i], m);
+ out[0] = stbi__compute_y(r, g, b);
+ out[1] = 255;
+ out += n;
+ }
+ } else if (z->s->img_n == 4 && z->app14_color_transform == 2) {
+ for (i = 0; i < z->s->img_x; ++i) {
+ out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]);
+ out[1] = 255;
+ out += n;
+ }
+ } else {
+ stbi_uc *y = coutput[0];
+ if (n == 1)
+ for (i = 0; i < z->s->img_x; ++i)
+ out[i] = y[i];
+ else
+ for (i = 0; i < z->s->img_x; ++i)
+ *out++ = y[i], *out++ = 255;
+ }
+ }
+ }
+ stbi__cleanup_jpeg(z);
+ *out_x = z->s->img_x;
+ *out_y = z->s->img_y;
+ if (comp)
+ *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output
+ return output;
+ }
+}
+
+static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) {
+ unsigned char *result;
+ stbi__jpeg *j = (stbi__jpeg *)stbi__malloc(sizeof(stbi__jpeg));
+ STBI_NOTUSED(ri);
+ j->s = s;
+ stbi__setup_jpeg(j);
+ result = load_jpeg_image(j, x, y, comp, req_comp);
+ STBI_FREE(j);
+ return result;
+}
+
+static int stbi__jpeg_test(stbi__context *s) {
+ int r;
+ stbi__jpeg *j = (stbi__jpeg *)stbi__malloc(sizeof(stbi__jpeg));
+ j->s = s;
+ stbi__setup_jpeg(j);
+ r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
+ stbi__rewind(s);
+ STBI_FREE(j);
+ return r;
+}
+
+static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) {
+ if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) {
+ stbi__rewind(j->s);
+ return 0;
+ }
+ if (x)
+ *x = j->s->img_x;
+ if (y)
+ *y = j->s->img_y;
+ if (comp)
+ *comp = j->s->img_n >= 3 ? 3 : 1;
+ return 1;
+}
+
+static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) {
+ int result;
+ stbi__jpeg *j = (stbi__jpeg *)(stbi__malloc(sizeof(stbi__jpeg)));
+ j->s = s;
+ result = stbi__jpeg_info_raw(j, x, y, comp);
+ STBI_FREE(j);
+ return result;
}
#endif
#ifndef STBI_NO_ZLIB
// fast-way is faster to check than jpeg huffman, but slow way is slower
-#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables
-#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1)
+#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables
+#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1)
// zlib-style huffman encoding
// (jpegs packs from left, zlib from right, so can't share code)
-typedef struct
-{
- stbi__uint16 fast[1 << STBI__ZFAST_BITS];
- stbi__uint16 firstcode[16];
- int maxcode[17];
- stbi__uint16 firstsymbol[16];
- stbi_uc size[288];
- stbi__uint16 value[288];
+typedef struct {
+ stbi__uint16 fast[1 << STBI__ZFAST_BITS];
+ stbi__uint16 firstcode[16];
+ int maxcode[17];
+ stbi__uint16 firstsymbol[16];
+ stbi_uc size[288];
+ stbi__uint16 value[288];
} stbi__zhuffman;
-stbi_inline static int stbi__bitreverse16(int n)
-{
- n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1);
- n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2);
- n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4);
- n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8);
- return n;
-}
-
-stbi_inline static int stbi__bit_reverse(int v, int bits)
-{
- STBI_ASSERT(bits <= 16);
- // to bit reverse n bits, reverse 16 and shift
- // e.g. 11 bits, bit reverse and shift away 5
- return stbi__bitreverse16(v) >> (16-bits);
-}
-
-static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num)
-{
- int i,k=0;
- int code, next_code[16], sizes[17];
-
- // DEFLATE spec for generating codes
- memset(sizes, 0, sizeof(sizes));
- memset(z->fast, 0, sizeof(z->fast));
- for (i=0; i < num; ++i)
- ++sizes[sizelist[i]];
- sizes[0] = 0;
- for (i=1; i < 16; ++i)
- if (sizes[i] > (1 << i))
- return stbi__err("bad sizes", "Corrupt PNG");
- code = 0;
- for (i=1; i < 16; ++i) {
- next_code[i] = code;
- z->firstcode[i] = (stbi__uint16) code;
- z->firstsymbol[i] = (stbi__uint16) k;
- code = (code + sizes[i]);
- if (sizes[i])
- if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG");
- z->maxcode[i] = code << (16-i); // preshift for inner loop
- code <<= 1;
- k += sizes[i];
- }
- z->maxcode[16] = 0x10000; // sentinel
- for (i=0; i < num; ++i) {
- int s = sizelist[i];
- if (s) {
- int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];
- stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i);
- z->size [c] = (stbi_uc ) s;
- z->value[c] = (stbi__uint16) i;
- if (s <= STBI__ZFAST_BITS) {
- int j = stbi__bit_reverse(next_code[s],s);
- while (j < (1 << STBI__ZFAST_BITS)) {
- z->fast[j] = fastv;
- j += (1 << s);
- }
- }
- ++next_code[s];
- }
- }
- return 1;
+stbi_inline static int stbi__bitreverse16(int n) {
+ n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1);
+ n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2);
+ n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4);
+ n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8);
+ return n;
+}
+
+stbi_inline static int stbi__bit_reverse(int v, int bits) {
+ STBI_ASSERT(bits <= 16);
+ // to bit reverse n bits, reverse 16 and shift
+ // e.g. 11 bits, bit reverse and shift away 5
+ return stbi__bitreverse16(v) >> (16 - bits);
+}
+
+static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) {
+ int i, k = 0;
+ int code, next_code[16], sizes[17];
+
+ // DEFLATE spec for generating codes
+ memset(sizes, 0, sizeof(sizes));
+ memset(z->fast, 0, sizeof(z->fast));
+ for (i = 0; i < num; ++i)
+ ++sizes[sizelist[i]];
+ sizes[0] = 0;
+ for (i = 1; i < 16; ++i)
+ if (sizes[i] > (1 << i))
+ return stbi__err("bad sizes", "Corrupt PNG");
+ code = 0;
+ for (i = 1; i < 16; ++i) {
+ next_code[i] = code;
+ z->firstcode[i] = (stbi__uint16)code;
+ z->firstsymbol[i] = (stbi__uint16)k;
+ code = (code + sizes[i]);
+ if (sizes[i])
+ if (code - 1 >= (1 << i))
+ return stbi__err("bad codelengths", "Corrupt PNG");
+ z->maxcode[i] = code << (16 - i); // preshift for inner loop
+ code <<= 1;
+ k += sizes[i];
+ }
+ z->maxcode[16] = 0x10000; // sentinel
+ for (i = 0; i < num; ++i) {
+ int s = sizelist[i];
+ if (s) {
+ int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];
+ stbi__uint16 fastv = (stbi__uint16)((s << 9) | i);
+ z->size[c] = (stbi_uc)s;
+ z->value[c] = (stbi__uint16)i;
+ if (s <= STBI__ZFAST_BITS) {
+ int j = stbi__bit_reverse(next_code[s], s);
+ while (j < (1 << STBI__ZFAST_BITS)) {
+ z->fast[j] = fastv;
+ j += (1 << s);
+ }
+ }
+ ++next_code[s];
+ }
+ }
+ return 1;
}
// zlib-from-memory implementation for PNG reading
// we require PNG read all the IDATs and combine them into a single
// memory buffer
-typedef struct
-{
- stbi_uc *zbuffer, *zbuffer_end;
- int num_bits;
- stbi__uint32 code_buffer;
+typedef struct {
+ stbi_uc *zbuffer, *zbuffer_end;
+ int num_bits;
+ stbi__uint32 code_buffer;
- char *zout;
- char *zout_start;
- char *zout_end;
- int z_expandable;
+ char *zout;
+ char *zout_start;
+ char *zout_end;
+ int z_expandable;
- stbi__zhuffman z_length, z_distance;
+ stbi__zhuffman z_length, z_distance;
} stbi__zbuf;
-stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)
-{
- if (z->zbuffer >= z->zbuffer_end) return 0;
- return *z->zbuffer++;
-}
-
-static void stbi__fill_bits(stbi__zbuf *z)
-{
- do {
- STBI_ASSERT(z->code_buffer < (1U << z->num_bits));
- z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;
- z->num_bits += 8;
- } while (z->num_bits <= 24);
-}
-
-stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n)
-{
- unsigned int k;
- if (z->num_bits < n) stbi__fill_bits(z);
- k = z->code_buffer & ((1 << n) - 1);
- z->code_buffer >>= n;
- z->num_bits -= n;
- return k;
-}
-
-static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
-{
- int b,s,k;
- // not resolved by fast table, so compute it the slow way
- // use jpeg approach, which requires MSbits at top
- k = stbi__bit_reverse(a->code_buffer, 16);
- for (s=STBI__ZFAST_BITS+1; ; ++s)
- if (k < z->maxcode[s])
- break;
- if (s == 16) return -1; // invalid code!
- // code size is s, so:
- b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
- STBI_ASSERT(z->size[b] == s);
- a->code_buffer >>= s;
- a->num_bits -= s;
- return z->value[b];
-}
-
-stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
-{
- int b,s;
- if (a->num_bits < 16) stbi__fill_bits(a);
- b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
- if (b) {
- s = b >> 9;
- a->code_buffer >>= s;
- a->num_bits -= s;
- return b & 511;
- }
- return stbi__zhuffman_decode_slowpath(a, z);
-}
-
-static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes
-{
- char *q;
- int cur, limit, old_limit;
- z->zout = zout;
- if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
- cur = (int) (z->zout - z->zout_start);
- limit = old_limit = (int) (z->zout_end - z->zout_start);
- while (cur + n > limit)
- limit *= 2;
- q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
- STBI_NOTUSED(old_limit);
- if (q == NULL) return stbi__err("outofmem", "Out of memory");
- z->zout_start = q;
- z->zout = q + cur;
- z->zout_end = q + limit;
- return 1;
-}
-
-static const int stbi__zlength_base[31] = {
- 3,4,5,6,7,8,9,10,11,13,
- 15,17,19,23,27,31,35,43,51,59,
- 67,83,99,115,131,163,195,227,258,0,0 };
-
-static const int stbi__zlength_extra[31]=
-{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
-
-static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,
-257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
-
-static const int stbi__zdist_extra[32] =
-{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
-
-static int stbi__parse_huffman_block(stbi__zbuf *a)
-{
- char *zout = a->zout;
- for(;;) {
- int z = stbi__zhuffman_decode(a, &a->z_length);
- if (z < 256) {
- if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes
- if (zout >= a->zout_end) {
- if (!stbi__zexpand(a, zout, 1)) return 0;
- zout = a->zout;
- }
- *zout++ = (char) z;
- } else {
- stbi_uc *p;
- int len,dist;
- if (z == 256) {
- a->zout = zout;
- return 1;
- }
- z -= 257;
- len = stbi__zlength_base[z];
- if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]);
- z = stbi__zhuffman_decode(a, &a->z_distance);
- if (z < 0) return stbi__err("bad huffman code","Corrupt PNG");
- dist = stbi__zdist_base[z];
- if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
- if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
- if (zout + len > a->zout_end) {
- if (!stbi__zexpand(a, zout, len)) return 0;
- zout = a->zout;
- }
- p = (stbi_uc *) (zout - dist);
- if (dist == 1) { // run of one byte; common in images.
- stbi_uc v = *p;
- if (len) { do *zout++ = v; while (--len); }
- } else {
- if (len) { do *zout++ = *p++; while (--len); }
- }
- }
- }
-}
-
-static int stbi__compute_huffman_codes(stbi__zbuf *a)
-{
- static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
- stbi__zhuffman z_codelength;
- stbi_uc lencodes[286+32+137];//padding for maximum single op
- stbi_uc codelength_sizes[19];
- int i,n;
-
- int hlit = stbi__zreceive(a,5) + 257;
- int hdist = stbi__zreceive(a,5) + 1;
- int hclen = stbi__zreceive(a,4) + 4;
- int ntot = hlit + hdist;
-
- memset(codelength_sizes, 0, sizeof(codelength_sizes));
- for (i=0; i < hclen; ++i) {
- int s = stbi__zreceive(a,3);
- codelength_sizes[length_dezigzag[i]] = (stbi_uc) s;
- }
- if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
-
- n = 0;
- while (n < ntot) {
- int c = stbi__zhuffman_decode(a, &z_codelength);
- if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG");
- if (c < 16)
- lencodes[n++] = (stbi_uc) c;
- else {
- stbi_uc fill = 0;
- if (c == 16) {
- c = stbi__zreceive(a,2)+3;
- if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
- fill = lencodes[n-1];
- } else if (c == 17)
- c = stbi__zreceive(a,3)+3;
- else {
- STBI_ASSERT(c == 18);
- c = stbi__zreceive(a,7)+11;
- }
- if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
- memset(lencodes+n, fill, c);
- n += c;
- }
- }
- if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG");
- if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
- if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;
- return 1;
-}
-
-static int stbi__parse_uncompressed_block(stbi__zbuf *a)
-{
- stbi_uc header[4];
- int len,nlen,k;
- if (a->num_bits & 7)
- stbi__zreceive(a, a->num_bits & 7); // discard
- // drain the bit-packed data into header
- k = 0;
- while (a->num_bits > 0) {
- header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check
- a->code_buffer >>= 8;
- a->num_bits -= 8;
- }
- STBI_ASSERT(a->num_bits == 0);
- // now fill header the normal way
- while (k < 4)
- header[k++] = stbi__zget8(a);
- len = header[1] * 256 + header[0];
- nlen = header[3] * 256 + header[2];
- if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG");
- if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG");
- if (a->zout + len > a->zout_end)
- if (!stbi__zexpand(a, a->zout, len)) return 0;
- memcpy(a->zout, a->zbuffer, len);
- a->zbuffer += len;
- a->zout += len;
- return 1;
-}
-
-static int stbi__parse_zlib_header(stbi__zbuf *a)
-{
- int cmf = stbi__zget8(a);
- int cm = cmf & 15;
- /* int cinfo = cmf >> 4; */
- int flg = stbi__zget8(a);
- if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
- if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png
- if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png
- // window = 1 << (8 + cinfo)... but who cares, we fully buffer output
- return 1;
-}
-
-static const stbi_uc stbi__zdefault_length[288] =
-{
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
- 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
- 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
- 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8
-};
-static const stbi_uc stbi__zdefault_distance[32] =
-{
- 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
-};
+stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) {
+ if (z->zbuffer >= z->zbuffer_end)
+ return 0;
+ return *z->zbuffer++;
+}
+
+static void stbi__fill_bits(stbi__zbuf *z) {
+ do {
+ STBI_ASSERT(z->code_buffer < (1U << z->num_bits));
+ z->code_buffer |= (unsigned int)stbi__zget8(z) << z->num_bits;
+ z->num_bits += 8;
+ } while (z->num_bits <= 24);
+}
+
+stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) {
+ unsigned int k;
+ if (z->num_bits < n)
+ stbi__fill_bits(z);
+ k = z->code_buffer & ((1 << n) - 1);
+ z->code_buffer >>= n;
+ z->num_bits -= n;
+ return k;
+}
+
+static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) {
+ int b, s, k;
+ // not resolved by fast table, so compute it the slow way
+ // use jpeg approach, which requires MSbits at top
+ k = stbi__bit_reverse(a->code_buffer, 16);
+ for (s = STBI__ZFAST_BITS + 1;; ++s)
+ if (k < z->maxcode[s])
+ break;
+ if (s == 16)
+ return -1; // invalid code!
+ // code size is s, so:
+ b = (k >> (16 - s)) - z->firstcode[s] + z->firstsymbol[s];
+ STBI_ASSERT(z->size[b] == s);
+ a->code_buffer >>= s;
+ a->num_bits -= s;
+ return z->value[b];
+}
+
+stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) {
+ int b, s;
+ if (a->num_bits < 16)
+ stbi__fill_bits(a);
+ b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
+ if (b) {
+ s = b >> 9;
+ a->code_buffer >>= s;
+ a->num_bits -= s;
+ return b & 511;
+ }
+ return stbi__zhuffman_decode_slowpath(a, z);
+}
+
+static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes
+{
+ char *q;
+ int cur, limit, old_limit;
+ z->zout = zout;
+ if (!z->z_expandable)
+ return stbi__err("output buffer limit", "Corrupt PNG");
+ cur = (int)(z->zout - z->zout_start);
+ limit = old_limit = (int)(z->zout_end - z->zout_start);
+ while (cur + n > limit)
+ limit *= 2;
+ q = (char *)STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
+ STBI_NOTUSED(old_limit);
+ if (q == NULL)
+ return stbi__err("outofmem", "Out of memory");
+ z->zout_start = q;
+ z->zout = q + cur;
+ z->zout_end = q + limit;
+ return 1;
+}
+
+static const int stbi__zlength_base[31] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+
+static const int stbi__zlength_extra[31] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0};
+
+static const int stbi__zdist_base[32] = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33,
+ 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
+ 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0};
+
+static const int stbi__zdist_extra[32] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
+ 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
+
+static int stbi__parse_huffman_block(stbi__zbuf *a) {
+ char *zout = a->zout;
+ for (;;) {
+ int z = stbi__zhuffman_decode(a, &a->z_length);
+ if (z < 256) {
+ if (z < 0)
+ return stbi__err("bad huffman code", "Corrupt PNG"); // error in huffman codes
+ if (zout >= a->zout_end) {
+ if (!stbi__zexpand(a, zout, 1))
+ return 0;
+ zout = a->zout;
+ }
+ *zout++ = (char)z;
+ } else {
+ stbi_uc *p;
+ int len, dist;
+ if (z == 256) {
+ a->zout = zout;
+ return 1;
+ }
+ z -= 257;
+ len = stbi__zlength_base[z];
+ if (stbi__zlength_extra[z])
+ len += stbi__zreceive(a, stbi__zlength_extra[z]);
+ z = stbi__zhuffman_decode(a, &a->z_distance);
+ if (z < 0)
+ return stbi__err("bad huffman code", "Corrupt PNG");
+ dist = stbi__zdist_base[z];
+ if (stbi__zdist_extra[z])
+ dist += stbi__zreceive(a, stbi__zdist_extra[z]);
+ if (zout - a->zout_start < dist)
+ return stbi__err("bad dist", "Corrupt PNG");
+ if (zout + len > a->zout_end) {
+ if (!stbi__zexpand(a, zout, len))
+ return 0;
+ zout = a->zout;
+ }
+ p = (stbi_uc *)(zout - dist);
+ if (dist == 1) { // run of one byte; common in images.
+ stbi_uc v = *p;
+ if (len) {
+ do
+ *zout++ = v;
+ while (--len);
+ }
+ } else {
+ if (len) {
+ do
+ *zout++ = *p++;
+ while (--len);
+ }
+ }
+ }
+ }
+}
+
+static int stbi__compute_huffman_codes(stbi__zbuf *a) {
+ static const stbi_uc length_dezigzag[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+ stbi__zhuffman z_codelength;
+ stbi_uc lencodes[286 + 32 + 137]; // padding for maximum single op
+ stbi_uc codelength_sizes[19];
+ int i, n;
+
+ int hlit = stbi__zreceive(a, 5) + 257;
+ int hdist = stbi__zreceive(a, 5) + 1;
+ int hclen = stbi__zreceive(a, 4) + 4;
+ int ntot = hlit + hdist;
+
+ memset(codelength_sizes, 0, sizeof(codelength_sizes));
+ for (i = 0; i < hclen; ++i) {
+ int s = stbi__zreceive(a, 3);
+ codelength_sizes[length_dezigzag[i]] = (stbi_uc)s;
+ }
+ if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19))
+ return 0;
+
+ n = 0;
+ while (n < ntot) {
+ int c = stbi__zhuffman_decode(a, &z_codelength);
+ if (c < 0 || c >= 19)
+ return stbi__err("bad codelengths", "Corrupt PNG");
+ if (c < 16)
+ lencodes[n++] = (stbi_uc)c;
+ else {
+ stbi_uc fill = 0;
+ if (c == 16) {
+ c = stbi__zreceive(a, 2) + 3;
+ if (n == 0)
+ return stbi__err("bad codelengths", "Corrupt PNG");
+ fill = lencodes[n - 1];
+ } else if (c == 17)
+ c = stbi__zreceive(a, 3) + 3;
+ else {
+ STBI_ASSERT(c == 18);
+ c = stbi__zreceive(a, 7) + 11;
+ }
+ if (ntot - n < c)
+ return stbi__err("bad codelengths", "Corrupt PNG");
+ memset(lencodes + n, fill, c);
+ n += c;
+ }
+ }
+ if (n != ntot)
+ return stbi__err("bad codelengths", "Corrupt PNG");
+ if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit))
+ return 0;
+ if (!stbi__zbuild_huffman(&a->z_distance, lencodes + hlit, hdist))
+ return 0;
+ return 1;
+}
+
+static int stbi__parse_uncompressed_block(stbi__zbuf *a) {
+ stbi_uc header[4];
+ int len, nlen, k;
+ if (a->num_bits & 7)
+ stbi__zreceive(a, a->num_bits & 7); // discard
+ // drain the bit-packed data into header
+ k = 0;
+ while (a->num_bits > 0) {
+ header[k++] = (stbi_uc)(a->code_buffer & 255); // suppress MSVC run-time check
+ a->code_buffer >>= 8;
+ a->num_bits -= 8;
+ }
+ STBI_ASSERT(a->num_bits == 0);
+ // now fill header the normal way
+ while (k < 4)
+ header[k++] = stbi__zget8(a);
+ len = header[1] * 256 + header[0];
+ nlen = header[3] * 256 + header[2];
+ if (nlen != (len ^ 0xffff))
+ return stbi__err("zlib corrupt", "Corrupt PNG");
+ if (a->zbuffer + len > a->zbuffer_end)
+ return stbi__err("read past buffer", "Corrupt PNG");
+ if (a->zout + len > a->zout_end)
+ if (!stbi__zexpand(a, a->zout, len))
+ return 0;
+ memcpy(a->zout, a->zbuffer, len);
+ a->zbuffer += len;
+ a->zout += len;
+ return 1;
+}
+
+static int stbi__parse_zlib_header(stbi__zbuf *a) {
+ int cmf = stbi__zget8(a);
+ int cm = cmf & 15;
+ /* int cinfo = cmf >> 4; */
+ int flg = stbi__zget8(a);
+ if ((cmf * 256 + flg) % 31 != 0)
+ return stbi__err("bad zlib header", "Corrupt PNG"); // zlib spec
+ if (flg & 32)
+ return stbi__err("no preset dict", "Corrupt PNG"); // preset dictionary not allowed in png
+ if (cm != 8)
+ return stbi__err("bad compression", "Corrupt PNG"); // DEFLATE required for png
+ // window = 1 << (8 + cinfo)... but who cares, we fully buffer output
+ return 1;
+}
+
+static const stbi_uc stbi__zdefault_length[288] = {
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8};
+static const stbi_uc stbi__zdefault_distance[32] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
/*
Init algorithm:
{
}
*/
-static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
-{
- int final, type;
- if (parse_header)
- if (!stbi__parse_zlib_header(a)) return 0;
- a->num_bits = 0;
- a->code_buffer = 0;
- do {
- final = stbi__zreceive(a,1);
- type = stbi__zreceive(a,2);
- if (type == 0) {
- if (!stbi__parse_uncompressed_block(a)) return 0;
- } else if (type == 3) {
- return 0;
- } else {
- if (type == 1) {
- // use fixed code lengths
- if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0;
- if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0;
- } else {
- if (!stbi__compute_huffman_codes(a)) return 0;
- }
- if (!stbi__parse_huffman_block(a)) return 0;
- }
- } while (!final);
- return 1;
-}
-
-static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header)
-{
- a->zout_start = obuf;
- a->zout = obuf;
- a->zout_end = obuf + olen;
- a->z_expandable = exp;
-
- return stbi__parse_zlib(a, parse_header);
-}
-
-STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)
-{
- stbi__zbuf a;
- char *p = (char *) stbi__malloc(initial_size);
- if (p == NULL) return NULL;
- a.zbuffer = (stbi_uc *) buffer;
- a.zbuffer_end = (stbi_uc *) buffer + len;
- if (stbi__do_zlib(&a, p, initial_size, 1, 1)) {
- if (outlen) *outlen = (int) (a.zout - a.zout_start);
- return a.zout_start;
- } else {
- STBI_FREE(a.zout_start);
- return NULL;
- }
-}
-
-STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen)
-{
- return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen);
-}
-
-STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header)
-{
- stbi__zbuf a;
- char *p = (char *) stbi__malloc(initial_size);
- if (p == NULL) return NULL;
- a.zbuffer = (stbi_uc *) buffer;
- a.zbuffer_end = (stbi_uc *) buffer + len;
- if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) {
- if (outlen) *outlen = (int) (a.zout - a.zout_start);
- return a.zout_start;
- } else {
- STBI_FREE(a.zout_start);
- return NULL;
- }
-}
-
-STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen)
-{
- stbi__zbuf a;
- a.zbuffer = (stbi_uc *) ibuffer;
- a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
- if (stbi__do_zlib(&a, obuffer, olen, 0, 1))
- return (int) (a.zout - a.zout_start);
- else
- return -1;
-}
-
-STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen)
-{
- stbi__zbuf a;
- char *p = (char *) stbi__malloc(16384);
- if (p == NULL) return NULL;
- a.zbuffer = (stbi_uc *) buffer;
- a.zbuffer_end = (stbi_uc *) buffer+len;
- if (stbi__do_zlib(&a, p, 16384, 1, 0)) {
- if (outlen) *outlen = (int) (a.zout - a.zout_start);
- return a.zout_start;
- } else {
- STBI_FREE(a.zout_start);
- return NULL;
- }
-}
-
-STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen)
-{
- stbi__zbuf a;
- a.zbuffer = (stbi_uc *) ibuffer;
- a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
- if (stbi__do_zlib(&a, obuffer, olen, 0, 0))
- return (int) (a.zout - a.zout_start);
- else
- return -1;
+static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) {
+ int final, type;
+ if (parse_header)
+ if (!stbi__parse_zlib_header(a))
+ return 0;
+ a->num_bits = 0;
+ a->code_buffer = 0;
+ do {
+ final = stbi__zreceive(a, 1);
+ type = stbi__zreceive(a, 2);
+ if (type == 0) {
+ if (!stbi__parse_uncompressed_block(a))
+ return 0;
+ } else if (type == 3) {
+ return 0;
+ } else {
+ if (type == 1) {
+ // use fixed code lengths
+ if (!stbi__zbuild_huffman(&a->z_length, stbi__zdefault_length, 288))
+ return 0;
+ if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32))
+ return 0;
+ } else {
+ if (!stbi__compute_huffman_codes(a))
+ return 0;
+ }
+ if (!stbi__parse_huffman_block(a))
+ return 0;
+ }
+ } while (!final);
+ return 1;
+}
+
+static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) {
+ a->zout_start = obuf;
+ a->zout = obuf;
+ a->zout_end = obuf + olen;
+ a->z_expandable = exp;
+
+ return stbi__parse_zlib(a, parse_header);
+}
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) {
+ stbi__zbuf a;
+ char *p = (char *)stbi__malloc(initial_size);
+ if (p == NULL)
+ return NULL;
+ a.zbuffer = (stbi_uc *)buffer;
+ a.zbuffer_end = (stbi_uc *)buffer + len;
+ if (stbi__do_zlib(&a, p, initial_size, 1, 1)) {
+ if (outlen)
+ *outlen = (int)(a.zout - a.zout_start);
+ return a.zout_start;
+ } else {
+ STBI_FREE(a.zout_start);
+ return NULL;
+ }
+}
+
+STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) {
+ return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen);
+}
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen,
+ int parse_header) {
+ stbi__zbuf a;
+ char *p = (char *)stbi__malloc(initial_size);
+ if (p == NULL)
+ return NULL;
+ a.zbuffer = (stbi_uc *)buffer;
+ a.zbuffer_end = (stbi_uc *)buffer + len;
+ if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) {
+ if (outlen)
+ *outlen = (int)(a.zout - a.zout_start);
+ return a.zout_start;
+ } else {
+ STBI_FREE(a.zout_start);
+ return NULL;
+ }
+}
+
+STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) {
+ stbi__zbuf a;
+ a.zbuffer = (stbi_uc *)ibuffer;
+ a.zbuffer_end = (stbi_uc *)ibuffer + ilen;
+ if (stbi__do_zlib(&a, obuffer, olen, 0, 1))
+ return (int)(a.zout - a.zout_start);
+ else
+ return -1;
+}
+
+STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) {
+ stbi__zbuf a;
+ char *p = (char *)stbi__malloc(16384);
+ if (p == NULL)
+ return NULL;
+ a.zbuffer = (stbi_uc *)buffer;
+ a.zbuffer_end = (stbi_uc *)buffer + len;
+ if (stbi__do_zlib(&a, p, 16384, 1, 0)) {
+ if (outlen)
+ *outlen = (int)(a.zout - a.zout_start);
+ return a.zout_start;
+ } else {
+ STBI_FREE(a.zout_start);
+ return NULL;
+ }
+}
+
+STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) {
+ stbi__zbuf a;
+ a.zbuffer = (stbi_uc *)ibuffer;
+ a.zbuffer_end = (stbi_uc *)ibuffer + ilen;
+ if (stbi__do_zlib(&a, obuffer, olen, 0, 0))
+ return (int)(a.zout - a.zout_start);
+ else
+ return -1;
}
#endif
// - uses stb_zlib, a PD zlib implementation with fast huffman decoding
#ifndef STBI_NO_PNG
-typedef struct
-{
- stbi__uint32 length;
- stbi__uint32 type;
+typedef struct {
+ stbi__uint32 length;
+ stbi__uint32 type;
} stbi__pngchunk;
-static stbi__pngchunk stbi__get_chunk_header(stbi__context *s)
-{
- stbi__pngchunk c;
- c.length = stbi__get32be(s);
- c.type = stbi__get32be(s);
- return c;
+static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) {
+ stbi__pngchunk c;
+ c.length = stbi__get32be(s);
+ c.type = stbi__get32be(s);
+ return c;
}
-static int stbi__check_png_header(stbi__context *s)
-{
- static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 };
- int i;
- for (i=0; i < 8; ++i)
- if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG");
- return 1;
+static int stbi__check_png_header(stbi__context *s) {
+ static const stbi_uc png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+ int i;
+ for (i = 0; i < 8; ++i)
+ if (stbi__get8(s) != png_sig[i])
+ return stbi__err("bad png sig", "Not a PNG");
+ return 1;
}
-typedef struct
-{
- stbi__context *s;
- stbi_uc *idata, *expanded, *out;
- int depth;
+typedef struct {
+ stbi__context *s;
+ stbi_uc *idata, *expanded, *out;
+ int depth;
} stbi__png;
-
enum {
- STBI__F_none=0,
- STBI__F_sub=1,
- STBI__F_up=2,
- STBI__F_avg=3,
- STBI__F_paeth=4,
- // synthetic filters used for first scanline to avoid needing a dummy row of 0s
- STBI__F_avg_first,
- STBI__F_paeth_first
+ STBI__F_none = 0,
+ STBI__F_sub = 1,
+ STBI__F_up = 2,
+ STBI__F_avg = 3,
+ STBI__F_paeth = 4,
+ // synthetic filters used for first scanline to avoid needing a dummy row of 0s
+ STBI__F_avg_first,
+ STBI__F_paeth_first
};
-static stbi_uc first_row_filter[5] =
-{
- STBI__F_none,
- STBI__F_sub,
- STBI__F_none,
- STBI__F_avg_first,
- STBI__F_paeth_first
-};
+static stbi_uc first_row_filter[5] = {STBI__F_none, STBI__F_sub, STBI__F_none, STBI__F_avg_first, STBI__F_paeth_first};
-static int stbi__paeth(int a, int b, int c)
-{
- int p = a + b - c;
- int pa = abs(p-a);
- int pb = abs(p-b);
- int pc = abs(p-c);
- if (pa <= pb && pa <= pc) return a;
- if (pb <= pc) return b;
- return c;
+static int stbi__paeth(int a, int b, int c) {
+ int p = a + b - c;
+ int pa = abs(p - a);
+ int pb = abs(p - b);
+ int pc = abs(p - c);
+ if (pa <= pb && pa <= pc)
+ return a;
+ if (pb <= pc)
+ return b;
+ return c;
}
-static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
+static const stbi_uc stbi__depth_scale_table[9] = {0, 0xff, 0x55, 0, 0x11, 0, 0, 0, 0x01};
// create the png data from post-deflated data
-static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
-{
- int bytes = (depth == 16? 2 : 1);
- stbi__context *s = a->s;
- stbi__uint32 i,j,stride = x*out_n*bytes;
- stbi__uint32 img_len, img_width_bytes;
- int k;
- int img_n = s->img_n; // copy it into a local for later
-
- int output_bytes = out_n*bytes;
- int filter_bytes = img_n*bytes;
- int width = x;
-
- STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
- a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
- if (!a->out) return stbi__err("outofmem", "Out of memory");
-
- if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
- img_width_bytes = (((img_n * x * depth) + 7) >> 3);
- img_len = (img_width_bytes + 1) * y;
-
- // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
- // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros),
- // so just check for raw_len < img_len always.
- if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
-
- for (j=0; j < y; ++j) {
- stbi_uc *cur = a->out + stride*j;
- stbi_uc *prior;
- int filter = *raw++;
-
- if (filter > 4)
- return stbi__err("invalid filter","Corrupt PNG");
-
- if (depth < 8) {
- STBI_ASSERT(img_width_bytes <= x);
- cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
- filter_bytes = 1;
- width = img_width_bytes;
- }
- prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
-
- // if first row, use special filter that doesn't sample previous row
- if (j == 0) filter = first_row_filter[filter];
-
- // handle first byte explicitly
- for (k=0; k < filter_bytes; ++k) {
- switch (filter) {
- case STBI__F_none : cur[k] = raw[k]; break;
- case STBI__F_sub : cur[k] = raw[k]; break;
- case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
- case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break;
- case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break;
- case STBI__F_avg_first : cur[k] = raw[k]; break;
- case STBI__F_paeth_first: cur[k] = raw[k]; break;
- }
- }
-
- if (depth == 8) {
- if (img_n != out_n)
- cur[img_n] = 255; // first pixel
- raw += img_n;
- cur += out_n;
- prior += out_n;
- } else if (depth == 16) {
- if (img_n != out_n) {
- cur[filter_bytes] = 255; // first pixel top byte
- cur[filter_bytes+1] = 255; // first pixel bottom byte
- }
- raw += filter_bytes;
- cur += output_bytes;
- prior += output_bytes;
- } else {
- raw += 1;
- cur += 1;
- prior += 1;
- }
-
- // this is a little gross, so that we don't switch per-pixel or per-component
- if (depth < 8 || img_n == out_n) {
- int nk = (width - 1)*filter_bytes;
- #define STBI__CASE(f) \
- case f: \
- for (k=0; k < nk; ++k)
- switch (filter) {
- // "none" filter turns into a memcpy here; make that explicit.
- case STBI__F_none: memcpy(cur, raw, nk); break;
- STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
- STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
- STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
- STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
- STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
- STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
- }
- #undef STBI__CASE
- raw += nk;
- } else {
- STBI_ASSERT(img_n+1 == out_n);
- #define STBI__CASE(f) \
- case f: \
- for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
- for (k=0; k < filter_bytes; ++k)
- switch (filter) {
- STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break;
- STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
- STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
- STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
- STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
- STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
- STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
- }
- #undef STBI__CASE
-
- // the loop above sets the high byte of the pixels' alpha, but for
- // 16 bit png files we also need the low byte set. we'll do that here.
- if (depth == 16) {
- cur = a->out + stride*j; // start at the beginning of the row again
- for (i=0; i < x; ++i,cur+=output_bytes) {
- cur[filter_bytes+1] = 255;
- }
- }
- }
- }
-
- // we make a separate pass to expand bits to pixels; for performance,
- // this could run two scanlines behind the above code, so it won't
- // intefere with filtering but will still be in the cache.
- if (depth < 8) {
- for (j=0; j < y; ++j) {
- stbi_uc *cur = a->out + stride*j;
- stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes;
- // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
- // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
- stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
-
- // note that the final byte might overshoot and write more data than desired.
- // we can allocate enough data that this never writes out of memory, but it
- // could also overwrite the next scanline. can it overwrite non-empty data
- // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
- // so we need to explicitly clamp the final ones
-
- if (depth == 4) {
- for (k=x*img_n; k >= 2; k-=2, ++in) {
- *cur++ = scale * ((*in >> 4) );
- *cur++ = scale * ((*in ) & 0x0f);
- }
- if (k > 0) *cur++ = scale * ((*in >> 4) );
- } else if (depth == 2) {
- for (k=x*img_n; k >= 4; k-=4, ++in) {
- *cur++ = scale * ((*in >> 6) );
- *cur++ = scale * ((*in >> 4) & 0x03);
- *cur++ = scale * ((*in >> 2) & 0x03);
- *cur++ = scale * ((*in ) & 0x03);
- }
- if (k > 0) *cur++ = scale * ((*in >> 6) );
- if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
- if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
- } else if (depth == 1) {
- for (k=x*img_n; k >= 8; k-=8, ++in) {
- *cur++ = scale * ((*in >> 7) );
- *cur++ = scale * ((*in >> 6) & 0x01);
- *cur++ = scale * ((*in >> 5) & 0x01);
- *cur++ = scale * ((*in >> 4) & 0x01);
- *cur++ = scale * ((*in >> 3) & 0x01);
- *cur++ = scale * ((*in >> 2) & 0x01);
- *cur++ = scale * ((*in >> 1) & 0x01);
- *cur++ = scale * ((*in ) & 0x01);
- }
- if (k > 0) *cur++ = scale * ((*in >> 7) );
- if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
- if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
- if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
- if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
- if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
- if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
- }
- if (img_n != out_n) {
- int q;
- // insert alpha = 255
- cur = a->out + stride*j;
- if (img_n == 1) {
- for (q=x-1; q >= 0; --q) {
- cur[q*2+1] = 255;
- cur[q*2+0] = cur[q];
- }
- } else {
- STBI_ASSERT(img_n == 3);
- for (q=x-1; q >= 0; --q) {
- cur[q*4+3] = 255;
- cur[q*4+2] = cur[q*3+2];
- cur[q*4+1] = cur[q*3+1];
- cur[q*4+0] = cur[q*3+0];
- }
- }
- }
- }
- } else if (depth == 16) {
- // force the image data from big-endian to platform-native.
- // this is done in a separate pass due to the decoding relying
- // on the data being untouched, but could probably be done
- // per-line during decode if care is taken.
- stbi_uc *cur = a->out;
- stbi__uint16 *cur16 = (stbi__uint16*)cur;
-
- for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
- *cur16 = (cur[0] << 8) | cur[1];
- }
- }
-
- return 1;
-}
-
-static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced)
-{
- int bytes = (depth == 16 ? 2 : 1);
- int out_bytes = out_n * bytes;
- stbi_uc *final;
- int p;
- if (!interlaced)
- return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color);
-
- // de-interlacing
- final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
- for (p=0; p < 7; ++p) {
- int xorig[] = { 0,4,0,2,0,1,0 };
- int yorig[] = { 0,0,4,0,2,0,1 };
- int xspc[] = { 8,8,4,4,2,2,1 };
- int yspc[] = { 8,8,8,4,4,2,2 };
- int i,j,x,y;
- // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1
- x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p];
- y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p];
- if (x && y) {
- stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y;
- if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) {
- STBI_FREE(final);
- return 0;
- }
- for (j=0; j < y; ++j) {
- for (i=0; i < x; ++i) {
- int out_y = j*yspc[p]+yorig[p];
- int out_x = i*xspc[p]+xorig[p];
- memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes,
- a->out + (j*x+i)*out_bytes, out_bytes);
- }
- }
- STBI_FREE(a->out);
- image_data += img_len;
- image_data_len -= img_len;
- }
- }
- a->out = final;
-
- return 1;
-}
-
-static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n)
-{
- stbi__context *s = z->s;
- stbi__uint32 i, pixel_count = s->img_x * s->img_y;
- stbi_uc *p = z->out;
-
- // compute color-based transparency, assuming we've
- // already got 255 as the alpha value in the output
- STBI_ASSERT(out_n == 2 || out_n == 4);
-
- if (out_n == 2) {
- for (i=0; i < pixel_count; ++i) {
- p[1] = (p[0] == tc[0] ? 0 : 255);
- p += 2;
- }
- } else {
- for (i=0; i < pixel_count; ++i) {
- if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
- p[3] = 0;
- p += 4;
- }
- }
- return 1;
-}
-
-static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n)
-{
- stbi__context *s = z->s;
- stbi__uint32 i, pixel_count = s->img_x * s->img_y;
- stbi__uint16 *p = (stbi__uint16*) z->out;
-
- // compute color-based transparency, assuming we've
- // already got 65535 as the alpha value in the output
- STBI_ASSERT(out_n == 2 || out_n == 4);
-
- if (out_n == 2) {
- for (i = 0; i < pixel_count; ++i) {
- p[1] = (p[0] == tc[0] ? 0 : 65535);
- p += 2;
- }
- } else {
- for (i = 0; i < pixel_count; ++i) {
- if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
- p[3] = 0;
- p += 4;
- }
- }
- return 1;
-}
-
-static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)
-{
- stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
- stbi_uc *p, *temp_out, *orig = a->out;
-
- p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0);
- if (p == NULL) return stbi__err("outofmem", "Out of memory");
-
- // between here and free(out) below, exitting would leak
- temp_out = p;
-
- if (pal_img_n == 3) {
- for (i=0; i < pixel_count; ++i) {
- int n = orig[i]*4;
- p[0] = palette[n ];
- p[1] = palette[n+1];
- p[2] = palette[n+2];
- p += 3;
- }
- } else {
- for (i=0; i < pixel_count; ++i) {
- int n = orig[i]*4;
- p[0] = palette[n ];
- p[1] = palette[n+1];
- p[2] = palette[n+2];
- p[3] = palette[n+3];
- p += 4;
- }
- }
- STBI_FREE(a->out);
- a->out = temp_out;
-
- STBI_NOTUSED(len);
-
- return 1;
+static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x,
+ stbi__uint32 y, int depth, int color) {
+ int bytes = (depth == 16 ? 2 : 1);
+ stbi__context *s = a->s;
+ stbi__uint32 i, j, stride = x * out_n * bytes;
+ stbi__uint32 img_len, img_width_bytes;
+ int k;
+ int img_n = s->img_n; // copy it into a local for later
+
+ int output_bytes = out_n * bytes;
+ int filter_bytes = img_n * bytes;
+ int width = x;
+
+ STBI_ASSERT(out_n == s->img_n || out_n == s->img_n + 1);
+ a->out = (stbi_uc *)stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
+ if (!a->out)
+ return stbi__err("outofmem", "Out of memory");
+
+ if (!stbi__mad3sizes_valid(img_n, x, depth, 7))
+ return stbi__err("too large", "Corrupt PNG");
+ img_width_bytes = (((img_n * x * depth) + 7) >> 3);
+ img_len = (img_width_bytes + 1) * y;
+
+ // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
+ // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros),
+ // so just check for raw_len < img_len always.
+ if (raw_len < img_len)
+ return stbi__err("not enough pixels", "Corrupt PNG");
+
+ for (j = 0; j < y; ++j) {
+ stbi_uc *cur = a->out + stride * j;
+ stbi_uc *prior;
+ int filter = *raw++;
+
+ if (filter > 4)
+ return stbi__err("invalid filter", "Corrupt PNG");
+
+ if (depth < 8) {
+ STBI_ASSERT(img_width_bytes <= x);
+ cur +=
+ x * out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
+ filter_bytes = 1;
+ width = img_width_bytes;
+ }
+ prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
+
+ // if first row, use special filter that doesn't sample previous row
+ if (j == 0)
+ filter = first_row_filter[filter];
+
+ // handle first byte explicitly
+ for (k = 0; k < filter_bytes; ++k) {
+ switch (filter) {
+ case STBI__F_none:
+ cur[k] = raw[k];
+ break;
+ case STBI__F_sub:
+ cur[k] = raw[k];
+ break;
+ case STBI__F_up:
+ cur[k] = STBI__BYTECAST(raw[k] + prior[k]);
+ break;
+ case STBI__F_avg:
+ cur[k] = STBI__BYTECAST(raw[k] + (prior[k] >> 1));
+ break;
+ case STBI__F_paeth:
+ cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0, prior[k], 0));
+ break;
+ case STBI__F_avg_first:
+ cur[k] = raw[k];
+ break;
+ case STBI__F_paeth_first:
+ cur[k] = raw[k];
+ break;
+ }
+ }
+
+ if (depth == 8) {
+ if (img_n != out_n)
+ cur[img_n] = 255; // first pixel
+ raw += img_n;
+ cur += out_n;
+ prior += out_n;
+ } else if (depth == 16) {
+ if (img_n != out_n) {
+ cur[filter_bytes] = 255; // first pixel top byte
+ cur[filter_bytes + 1] = 255; // first pixel bottom byte
+ }
+ raw += filter_bytes;
+ cur += output_bytes;
+ prior += output_bytes;
+ } else {
+ raw += 1;
+ cur += 1;
+ prior += 1;
+ }
+
+ // this is a little gross, so that we don't switch per-pixel or per-component
+ if (depth < 8 || img_n == out_n) {
+ int nk = (width - 1) * filter_bytes;
+#define STBI__CASE(f) \
+ case f: \
+ for (k = 0; k < nk; ++k)
+ switch (filter) {
+ // "none" filter turns into a memcpy here; make that explicit.
+ case STBI__F_none:
+ memcpy(cur, raw, nk);
+ break;
+ STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k - filter_bytes]); }
+ break;
+ STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); }
+ break;
+ STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k - filter_bytes]) >> 1)); }
+ break;
+ STBI__CASE(STBI__F_paeth) {
+ cur[k] =
+ STBI__BYTECAST(raw[k] + stbi__paeth(cur[k - filter_bytes], prior[k], prior[k - filter_bytes]));
+ }
+ break;
+ STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k - filter_bytes] >> 1)); }
+ break;
+ STBI__CASE(STBI__F_paeth_first) {
+ cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k - filter_bytes], 0, 0));
+ }
+ break;
+ }
+#undef STBI__CASE
+ raw += nk;
+ } else {
+ STBI_ASSERT(img_n + 1 == out_n);
+#define STBI__CASE(f) \
+ case f: \
+ for (i = x - 1; i >= 1; \
+ --i, cur[filter_bytes] = 255, raw += filter_bytes, cur += output_bytes, prior += output_bytes) \
+ for (k = 0; k < filter_bytes; ++k)
+ switch (filter) {
+ STBI__CASE(STBI__F_none) { cur[k] = raw[k]; }
+ break;
+ STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k - output_bytes]); }
+ break;
+ STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); }
+ break;
+ STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k - output_bytes]) >> 1)); }
+ break;
+ STBI__CASE(STBI__F_paeth) {
+ cur[k] =
+ STBI__BYTECAST(raw[k] + stbi__paeth(cur[k - output_bytes], prior[k], prior[k - output_bytes]));
+ }
+ break;
+ STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k - output_bytes] >> 1)); }
+ break;
+ STBI__CASE(STBI__F_paeth_first) {
+ cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k - output_bytes], 0, 0));
+ }
+ break;
+ }
+#undef STBI__CASE
+
+ // the loop above sets the high byte of the pixels' alpha, but for
+ // 16 bit png files we also need the low byte set. we'll do that here.
+ if (depth == 16) {
+ cur = a->out + stride * j; // start at the beginning of the row again
+ for (i = 0; i < x; ++i, cur += output_bytes) {
+ cur[filter_bytes + 1] = 255;
+ }
+ }
+ }
+ }
+
+ // we make a separate pass to expand bits to pixels; for performance,
+ // this could run two scanlines behind the above code, so it won't
+ // intefere with filtering but will still be in the cache.
+ if (depth < 8) {
+ for (j = 0; j < y; ++j) {
+ stbi_uc *cur = a->out + stride * j;
+ stbi_uc *in = a->out + stride * j + x * out_n - img_width_bytes;
+ // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for
+ // 1/2/4-bit png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data
+ // that will be skipped in the later loop
+ stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
+
+ // note that the final byte might overshoot and write more data than desired.
+ // we can allocate enough data that this never writes out of memory, but it
+ // could also overwrite the next scanline. can it overwrite non-empty data
+ // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
+ // so we need to explicitly clamp the final ones
+
+ if (depth == 4) {
+ for (k = x * img_n; k >= 2; k -= 2, ++in) {
+ *cur++ = scale * ((*in >> 4));
+ *cur++ = scale * ((*in) & 0x0f);
+ }
+ if (k > 0)
+ *cur++ = scale * ((*in >> 4));
+ } else if (depth == 2) {
+ for (k = x * img_n; k >= 4; k -= 4, ++in) {
+ *cur++ = scale * ((*in >> 6));
+ *cur++ = scale * ((*in >> 4) & 0x03);
+ *cur++ = scale * ((*in >> 2) & 0x03);
+ *cur++ = scale * ((*in) & 0x03);
+ }
+ if (k > 0)
+ *cur++ = scale * ((*in >> 6));
+ if (k > 1)
+ *cur++ = scale * ((*in >> 4) & 0x03);
+ if (k > 2)
+ *cur++ = scale * ((*in >> 2) & 0x03);
+ } else if (depth == 1) {
+ for (k = x * img_n; k >= 8; k -= 8, ++in) {
+ *cur++ = scale * ((*in >> 7));
+ *cur++ = scale * ((*in >> 6) & 0x01);
+ *cur++ = scale * ((*in >> 5) & 0x01);
+ *cur++ = scale * ((*in >> 4) & 0x01);
+ *cur++ = scale * ((*in >> 3) & 0x01);
+ *cur++ = scale * ((*in >> 2) & 0x01);
+ *cur++ = scale * ((*in >> 1) & 0x01);
+ *cur++ = scale * ((*in) & 0x01);
+ }
+ if (k > 0)
+ *cur++ = scale * ((*in >> 7));
+ if (k > 1)
+ *cur++ = scale * ((*in >> 6) & 0x01);
+ if (k > 2)
+ *cur++ = scale * ((*in >> 5) & 0x01);
+ if (k > 3)
+ *cur++ = scale * ((*in >> 4) & 0x01);
+ if (k > 4)
+ *cur++ = scale * ((*in >> 3) & 0x01);
+ if (k > 5)
+ *cur++ = scale * ((*in >> 2) & 0x01);
+ if (k > 6)
+ *cur++ = scale * ((*in >> 1) & 0x01);
+ }
+ if (img_n != out_n) {
+ int q;
+ // insert alpha = 255
+ cur = a->out + stride * j;
+ if (img_n == 1) {
+ for (q = x - 1; q >= 0; --q) {
+ cur[q * 2 + 1] = 255;
+ cur[q * 2 + 0] = cur[q];
+ }
+ } else {
+ STBI_ASSERT(img_n == 3);
+ for (q = x - 1; q >= 0; --q) {
+ cur[q * 4 + 3] = 255;
+ cur[q * 4 + 2] = cur[q * 3 + 2];
+ cur[q * 4 + 1] = cur[q * 3 + 1];
+ cur[q * 4 + 0] = cur[q * 3 + 0];
+ }
+ }
+ }
+ }
+ } else if (depth == 16) {
+ // force the image data from big-endian to platform-native.
+ // this is done in a separate pass due to the decoding relying
+ // on the data being untouched, but could probably be done
+ // per-line during decode if care is taken.
+ stbi_uc *cur = a->out;
+ stbi__uint16 *cur16 = (stbi__uint16 *)cur;
+
+ for (i = 0; i < x * y * out_n; ++i, cur16++, cur += 2) {
+ *cur16 = (cur[0] << 8) | cur[1];
+ }
+ }
+
+ return 1;
+}
+
+static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth,
+ int color, int interlaced) {
+ int bytes = (depth == 16 ? 2 : 1);
+ int out_bytes = out_n * bytes;
+ stbi_uc *final;
+ int p;
+ if (!interlaced)
+ return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color);
+
+ // de-interlacing
+ final = (stbi_uc *)stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
+ for (p = 0; p < 7; ++p) {
+ int xorig[] = {0, 4, 0, 2, 0, 1, 0};
+ int yorig[] = {0, 0, 4, 0, 2, 0, 1};
+ int xspc[] = {8, 8, 4, 4, 2, 2, 1};
+ int yspc[] = {8, 8, 8, 4, 4, 2, 2};
+ int i, j, x, y;
+ // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1
+ x = (a->s->img_x - xorig[p] + xspc[p] - 1) / xspc[p];
+ y = (a->s->img_y - yorig[p] + yspc[p] - 1) / yspc[p];
+ if (x && y) {
+ stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y;
+ if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) {
+ STBI_FREE(final);
+ return 0;
+ }
+ for (j = 0; j < y; ++j) {
+ for (i = 0; i < x; ++i) {
+ int out_y = j * yspc[p] + yorig[p];
+ int out_x = i * xspc[p] + xorig[p];
+ memcpy(final + out_y * a->s->img_x * out_bytes + out_x * out_bytes,
+ a->out + (j * x + i) * out_bytes, out_bytes);
+ }
+ }
+ STBI_FREE(a->out);
+ image_data += img_len;
+ image_data_len -= img_len;
+ }
+ }
+ a->out = final;
+
+ return 1;
+}
+
+static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) {
+ stbi__context *s = z->s;
+ stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+ stbi_uc *p = z->out;
+
+ // compute color-based transparency, assuming we've
+ // already got 255 as the alpha value in the output
+ STBI_ASSERT(out_n == 2 || out_n == 4);
+
+ if (out_n == 2) {
+ for (i = 0; i < pixel_count; ++i) {
+ p[1] = (p[0] == tc[0] ? 0 : 255);
+ p += 2;
+ }
+ } else {
+ for (i = 0; i < pixel_count; ++i) {
+ if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
+ p[3] = 0;
+ p += 4;
+ }
+ }
+ return 1;
+}
+
+static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) {
+ stbi__context *s = z->s;
+ stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+ stbi__uint16 *p = (stbi__uint16 *)z->out;
+
+ // compute color-based transparency, assuming we've
+ // already got 65535 as the alpha value in the output
+ STBI_ASSERT(out_n == 2 || out_n == 4);
+
+ if (out_n == 2) {
+ for (i = 0; i < pixel_count; ++i) {
+ p[1] = (p[0] == tc[0] ? 0 : 65535);
+ p += 2;
+ }
+ } else {
+ for (i = 0; i < pixel_count; ++i) {
+ if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
+ p[3] = 0;
+ p += 4;
+ }
+ }
+ return 1;
+}
+
+static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) {
+ stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
+ stbi_uc *p, *temp_out, *orig = a->out;
+
+ p = (stbi_uc *)stbi__malloc_mad2(pixel_count, pal_img_n, 0);
+ if (p == NULL)
+ return stbi__err("outofmem", "Out of memory");
+
+ // between here and free(out) below, exitting would leak
+ temp_out = p;
+
+ if (pal_img_n == 3) {
+ for (i = 0; i < pixel_count; ++i) {
+ int n = orig[i] * 4;
+ p[0] = palette[n];
+ p[1] = palette[n + 1];
+ p[2] = palette[n + 2];
+ p += 3;
+ }
+ } else {
+ for (i = 0; i < pixel_count; ++i) {
+ int n = orig[i] * 4;
+ p[0] = palette[n];
+ p[1] = palette[n + 1];
+ p[2] = palette[n + 2];
+ p[3] = palette[n + 3];
+ p += 4;
+ }
+ }
+ STBI_FREE(a->out);
+ a->out = temp_out;
+
+ STBI_NOTUSED(len);
+
+ return 1;
}
static int stbi__unpremultiply_on_load = 0;
-static int stbi__de_iphone_flag = 0;
-
-STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply)
-{
- stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply;
-}
-
-STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
-{
- stbi__de_iphone_flag = flag_true_if_should_convert;
-}
-
-static void stbi__de_iphone(stbi__png *z)
-{
- stbi__context *s = z->s;
- stbi__uint32 i, pixel_count = s->img_x * s->img_y;
- stbi_uc *p = z->out;
-
- if (s->img_out_n == 3) { // convert bgr to rgb
- for (i=0; i < pixel_count; ++i) {
- stbi_uc t = p[0];
- p[0] = p[2];
- p[2] = t;
- p += 3;
- }
- } else {
- STBI_ASSERT(s->img_out_n == 4);
- if (stbi__unpremultiply_on_load) {
- // convert bgr to rgb and unpremultiply
- for (i=0; i < pixel_count; ++i) {
- stbi_uc a = p[3];
- stbi_uc t = p[0];
- if (a) {
- stbi_uc half = a / 2;
- p[0] = (p[2] * 255 + half) / a;
- p[1] = (p[1] * 255 + half) / a;
- p[2] = ( t * 255 + half) / a;
- } else {
- p[0] = p[2];
- p[2] = t;
- }
- p += 4;
- }
- } else {
- // convert bgr to rgb
- for (i=0; i < pixel_count; ++i) {
- stbi_uc t = p[0];
- p[0] = p[2];
- p[2] = t;
- p += 4;
- }
- }
- }
-}
-
-#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d))
-
-static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
-{
- stbi_uc palette[1024], pal_img_n=0;
- stbi_uc has_trans=0, tc[3];
- stbi__uint16 tc16[3];
- stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
- int first=1,k,interlace=0, color=0, is_iphone=0;
- stbi__context *s = z->s;
-
- z->expanded = NULL;
- z->idata = NULL;
- z->out = NULL;
-
- if (!stbi__check_png_header(s)) return 0;
-
- if (scan == STBI__SCAN_type) return 1;
-
- for (;;) {
- stbi__pngchunk c = stbi__get_chunk_header(s);
- switch (c.type) {
- case STBI__PNG_TYPE('C','g','B','I'):
- is_iphone = 1;
- stbi__skip(s, c.length);
- break;
- case STBI__PNG_TYPE('I','H','D','R'): {
- int comp,filter;
- if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
- first = 0;
- if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
- s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
- s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
- z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
- color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG");
- if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG");
- if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
- comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG");
- filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG");
- interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG");
- if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG");
- if (!pal_img_n) {
- s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
- if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");
- if (scan == STBI__SCAN_header) return 1;
- } else {
- // if paletted, then pal_n is our final components, and
- // img_n is # components to decompress/filter.
- s->img_n = 1;
- if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG");
- // if SCAN_header, have to scan to see if we have a tRNS
- }
- break;
- }
-
- case STBI__PNG_TYPE('P','L','T','E'): {
- if (first) return stbi__err("first not IHDR", "Corrupt PNG");
- if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG");
- pal_len = c.length / 3;
- if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG");
- for (i=0; i < pal_len; ++i) {
- palette[i*4+0] = stbi__get8(s);
- palette[i*4+1] = stbi__get8(s);
- palette[i*4+2] = stbi__get8(s);
- palette[i*4+3] = 255;
- }
- break;
- }
-
- case STBI__PNG_TYPE('t','R','N','S'): {
- if (first) return stbi__err("first not IHDR", "Corrupt PNG");
- if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG");
- if (pal_img_n) {
- if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; }
- if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG");
- if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG");
- pal_img_n = 4;
- for (i=0; i < c.length; ++i)
- palette[i*4+3] = stbi__get8(s);
- } else {
- if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
- if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
- has_trans = 1;
- if (z->depth == 16) {
- for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
- } else {
- for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
- }
- }
- break;
- }
-
- case STBI__PNG_TYPE('I','D','A','T'): {
- if (first) return stbi__err("first not IHDR", "Corrupt PNG");
- if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");
- if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
- if ((int)(ioff + c.length) < (int)ioff) return 0;
- if (ioff + c.length > idata_limit) {
- stbi__uint32 idata_limit_old = idata_limit;
- stbi_uc *p;
- if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
- while (ioff + c.length > idata_limit)
- idata_limit *= 2;
- STBI_NOTUSED(idata_limit_old);
- p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory");
- z->idata = p;
- }
- if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG");
- ioff += c.length;
- break;
- }
-
- case STBI__PNG_TYPE('I','E','N','D'): {
- stbi__uint32 raw_len, bpl;
- if (first) return stbi__err("first not IHDR", "Corrupt PNG");
- if (scan != STBI__SCAN_load) return 1;
- if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");
- // initial guess for decoded data size to avoid unnecessary reallocs
- bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component
- raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
- z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);
- if (z->expanded == NULL) return 0; // zlib should set error
- STBI_FREE(z->idata); z->idata = NULL;
- if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans)
- s->img_out_n = s->img_n+1;
- else
- s->img_out_n = s->img_n;
- if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;
- if (has_trans) {
- if (z->depth == 16) {
- if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0;
- } else {
- if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
- }
- }
- if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
- stbi__de_iphone(z);
- if (pal_img_n) {
- // pal_img_n == 3 or 4
- s->img_n = pal_img_n; // record the actual colors we had
- s->img_out_n = pal_img_n;
- if (req_comp >= 3) s->img_out_n = req_comp;
- if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n))
- return 0;
- } else if (has_trans) {
- // non-paletted image with tRNS -> source image has (constant) alpha
- ++s->img_n;
- }
- STBI_FREE(z->expanded); z->expanded = NULL;
- return 1;
- }
-
- default:
- // if critical, fail
- if (first) return stbi__err("first not IHDR", "Corrupt PNG");
- if ((c.type & (1 << 29)) == 0) {
- #ifndef STBI_NO_FAILURE_STRINGS
- // not threadsafe
- static char invalid_chunk[] = "XXXX PNG chunk not known";
- invalid_chunk[0] = STBI__BYTECAST(c.type >> 24);
- invalid_chunk[1] = STBI__BYTECAST(c.type >> 16);
- invalid_chunk[2] = STBI__BYTECAST(c.type >> 8);
- invalid_chunk[3] = STBI__BYTECAST(c.type >> 0);
- #endif
- return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type");
- }
- stbi__skip(s, c.length);
- break;
- }
- // end of PNG chunk, read and skip CRC
- stbi__get32be(s);
- }
-}
-
-static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri)
-{
- void *result=NULL;
- if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
- if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
- if (p->depth < 8)
- ri->bits_per_channel = 8;
- else
- ri->bits_per_channel = p->depth;
- result = p->out;
- p->out = NULL;
- if (req_comp && req_comp != p->s->img_out_n) {
- if (ri->bits_per_channel == 8)
- result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
- else
- result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
- p->s->img_out_n = req_comp;
- if (result == NULL) return result;
- }
- *x = p->s->img_x;
- *y = p->s->img_y;
- if (n) *n = p->s->img_n;
- }
- STBI_FREE(p->out); p->out = NULL;
- STBI_FREE(p->expanded); p->expanded = NULL;
- STBI_FREE(p->idata); p->idata = NULL;
-
- return result;
-}
-
-static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
-{
- stbi__png p;
- p.s = s;
- return stbi__do_png(&p, x,y,comp,req_comp, ri);
-}
-
-static int stbi__png_test(stbi__context *s)
-{
- int r;
- r = stbi__check_png_header(s);
- stbi__rewind(s);
- return r;
-}
-
-static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp)
-{
- if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) {
- stbi__rewind( p->s );
- return 0;
- }
- if (x) *x = p->s->img_x;
- if (y) *y = p->s->img_y;
- if (comp) *comp = p->s->img_n;
- return 1;
-}
-
-static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp)
-{
- stbi__png p;
- p.s = s;
- return stbi__png_info_raw(&p, x, y, comp);
-}
-
-static int stbi__png_is16(stbi__context *s)
-{
- stbi__png p;
- p.s = s;
- if (!stbi__png_info_raw(&p, NULL, NULL, NULL))
- return 0;
- if (p.depth != 16) {
- stbi__rewind(p.s);
- return 0;
- }
- return 1;
+static int stbi__de_iphone_flag = 0;
+
+STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) {
+ stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply;
+}
+
+STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) {
+ stbi__de_iphone_flag = flag_true_if_should_convert;
+}
+
+static void stbi__de_iphone(stbi__png *z) {
+ stbi__context *s = z->s;
+ stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+ stbi_uc *p = z->out;
+
+ if (s->img_out_n == 3) { // convert bgr to rgb
+ for (i = 0; i < pixel_count; ++i) {
+ stbi_uc t = p[0];
+ p[0] = p[2];
+ p[2] = t;
+ p += 3;
+ }
+ } else {
+ STBI_ASSERT(s->img_out_n == 4);
+ if (stbi__unpremultiply_on_load) {
+ // convert bgr to rgb and unpremultiply
+ for (i = 0; i < pixel_count; ++i) {
+ stbi_uc a = p[3];
+ stbi_uc t = p[0];
+ if (a) {
+ stbi_uc half = a / 2;
+ p[0] = (p[2] * 255 + half) / a;
+ p[1] = (p[1] * 255 + half) / a;
+ p[2] = (t * 255 + half) / a;
+ } else {
+ p[0] = p[2];
+ p[2] = t;
+ }
+ p += 4;
+ }
+ } else {
+ // convert bgr to rgb
+ for (i = 0; i < pixel_count; ++i) {
+ stbi_uc t = p[0];
+ p[0] = p[2];
+ p[2] = t;
+ p += 4;
+ }
+ }
+ }
+}
+
+#define STBI__PNG_TYPE(a, b, c, d) \
+ (((unsigned)(a) << 24) + ((unsigned)(b) << 16) + ((unsigned)(c) << 8) + (unsigned)(d))
+
+static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) {
+ stbi_uc palette[1024], pal_img_n = 0;
+ stbi_uc has_trans = 0, tc[3];
+ stbi__uint16 tc16[3];
+ stbi__uint32 ioff = 0, idata_limit = 0, i, pal_len = 0;
+ int first = 1, k, interlace = 0, color = 0, is_iphone = 0;
+ stbi__context *s = z->s;
+
+ z->expanded = NULL;
+ z->idata = NULL;
+ z->out = NULL;
+
+ if (!stbi__check_png_header(s))
+ return 0;
+
+ if (scan == STBI__SCAN_type)
+ return 1;
+
+ for (;;) {
+ stbi__pngchunk c = stbi__get_chunk_header(s);
+ switch (c.type) {
+ case STBI__PNG_TYPE('C', 'g', 'B', 'I'):
+ is_iphone = 1;
+ stbi__skip(s, c.length);
+ break;
+ case STBI__PNG_TYPE('I', 'H', 'D', 'R'): {
+ int comp, filter;
+ if (!first)
+ return stbi__err("multiple IHDR", "Corrupt PNG");
+ first = 0;
+ if (c.length != 13)
+ return stbi__err("bad IHDR len", "Corrupt PNG");
+ s->img_x = stbi__get32be(s);
+ if (s->img_x > (1 << 24))
+ return stbi__err("too large", "Very large image (corrupt?)");
+ s->img_y = stbi__get32be(s);
+ if (s->img_y > (1 << 24))
+ return stbi__err("too large", "Very large image (corrupt?)");
+ z->depth = stbi__get8(s);
+ if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16)
+ return stbi__err("1/2/4/8/16-bit only", "PNG not supported: 1/2/4/8/16-bit only");
+ color = stbi__get8(s);
+ if (color > 6)
+ return stbi__err("bad ctype", "Corrupt PNG");
+ if (color == 3 && z->depth == 16)
+ return stbi__err("bad ctype", "Corrupt PNG");
+ if (color == 3)
+ pal_img_n = 3;
+ else if (color & 1)
+ return stbi__err("bad ctype", "Corrupt PNG");
+ comp = stbi__get8(s);
+ if (comp)
+ return stbi__err("bad comp method", "Corrupt PNG");
+ filter = stbi__get8(s);
+ if (filter)
+ return stbi__err("bad filter method", "Corrupt PNG");
+ interlace = stbi__get8(s);
+ if (interlace > 1)
+ return stbi__err("bad interlace method", "Corrupt PNG");
+ if (!s->img_x || !s->img_y)
+ return stbi__err("0-pixel image", "Corrupt PNG");
+ if (!pal_img_n) {
+ s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
+ if ((1 << 30) / s->img_x / s->img_n < s->img_y)
+ return stbi__err("too large", "Image too large to decode");
+ if (scan == STBI__SCAN_header)
+ return 1;
+ } else {
+ // if paletted, then pal_n is our final components, and
+ // img_n is # components to decompress/filter.
+ s->img_n = 1;
+ if ((1 << 30) / s->img_x / 4 < s->img_y)
+ return stbi__err("too large", "Corrupt PNG");
+ // if SCAN_header, have to scan to see if we have a tRNS
+ }
+ break;
+ }
+
+ case STBI__PNG_TYPE('P', 'L', 'T', 'E'): {
+ if (first)
+ return stbi__err("first not IHDR", "Corrupt PNG");
+ if (c.length > 256 * 3)
+ return stbi__err("invalid PLTE", "Corrupt PNG");
+ pal_len = c.length / 3;
+ if (pal_len * 3 != c.length)
+ return stbi__err("invalid PLTE", "Corrupt PNG");
+ for (i = 0; i < pal_len; ++i) {
+ palette[i * 4 + 0] = stbi__get8(s);
+ palette[i * 4 + 1] = stbi__get8(s);
+ palette[i * 4 + 2] = stbi__get8(s);
+ palette[i * 4 + 3] = 255;
+ }
+ break;
+ }
+
+ case STBI__PNG_TYPE('t', 'R', 'N', 'S'): {
+ if (first)
+ return stbi__err("first not IHDR", "Corrupt PNG");
+ if (z->idata)
+ return stbi__err("tRNS after IDAT", "Corrupt PNG");
+ if (pal_img_n) {
+ if (scan == STBI__SCAN_header) {
+ s->img_n = 4;
+ return 1;
+ }
+ if (pal_len == 0)
+ return stbi__err("tRNS before PLTE", "Corrupt PNG");
+ if (c.length > pal_len)
+ return stbi__err("bad tRNS len", "Corrupt PNG");
+ pal_img_n = 4;
+ for (i = 0; i < c.length; ++i)
+ palette[i * 4 + 3] = stbi__get8(s);
+ } else {
+ if (!(s->img_n & 1))
+ return stbi__err("tRNS with alpha", "Corrupt PNG");
+ if (c.length != (stbi__uint32)s->img_n * 2)
+ return stbi__err("bad tRNS len", "Corrupt PNG");
+ has_trans = 1;
+ if (z->depth == 16) {
+ for (k = 0; k < s->img_n; ++k)
+ tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
+ } else {
+ for (k = 0; k < s->img_n; ++k)
+ tc[k] = (stbi_uc)(stbi__get16be(s) & 255) *
+ stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
+ }
+ }
+ break;
+ }
+
+ case STBI__PNG_TYPE('I', 'D', 'A', 'T'): {
+ if (first)
+ return stbi__err("first not IHDR", "Corrupt PNG");
+ if (pal_img_n && !pal_len)
+ return stbi__err("no PLTE", "Corrupt PNG");
+ if (scan == STBI__SCAN_header) {
+ s->img_n = pal_img_n;
+ return 1;
+ }
+ if ((int)(ioff + c.length) < (int)ioff)
+ return 0;
+ if (ioff + c.length > idata_limit) {
+ stbi__uint32 idata_limit_old = idata_limit;
+ stbi_uc *p;
+ if (idata_limit == 0)
+ idata_limit = c.length > 4096 ? c.length : 4096;
+ while (ioff + c.length > idata_limit)
+ idata_limit *= 2;
+ STBI_NOTUSED(idata_limit_old);
+ p = (stbi_uc *)STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit);
+ if (p == NULL)
+ return stbi__err("outofmem", "Out of memory");
+ z->idata = p;
+ }
+ if (!stbi__getn(s, z->idata + ioff, c.length))
+ return stbi__err("outofdata", "Corrupt PNG");
+ ioff += c.length;
+ break;
+ }
+
+ case STBI__PNG_TYPE('I', 'E', 'N', 'D'): {
+ stbi__uint32 raw_len, bpl;
+ if (first)
+ return stbi__err("first not IHDR", "Corrupt PNG");
+ if (scan != STBI__SCAN_load)
+ return 1;
+ if (z->idata == NULL)
+ return stbi__err("no IDAT", "Corrupt PNG");
+ // initial guess for decoded data size to avoid unnecessary reallocs
+ bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component
+ raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
+ z->expanded = (stbi_uc *)stbi_zlib_decode_malloc_guesssize_headerflag((char *)z->idata, ioff, raw_len,
+ (int *)&raw_len, !is_iphone);
+ if (z->expanded == NULL)
+ return 0; // zlib should set error
+ STBI_FREE(z->idata);
+ z->idata = NULL;
+ if ((req_comp == s->img_n + 1 && req_comp != 3 && !pal_img_n) || has_trans)
+ s->img_out_n = s->img_n + 1;
+ else
+ s->img_out_n = s->img_n;
+ if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace))
+ return 0;
+ if (has_trans) {
+ if (z->depth == 16) {
+ if (!stbi__compute_transparency16(z, tc16, s->img_out_n))
+ return 0;
+ } else {
+ if (!stbi__compute_transparency(z, tc, s->img_out_n))
+ return 0;
+ }
+ }
+ if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
+ stbi__de_iphone(z);
+ if (pal_img_n) {
+ // pal_img_n == 3 or 4
+ s->img_n = pal_img_n; // record the actual colors we had
+ s->img_out_n = pal_img_n;
+ if (req_comp >= 3)
+ s->img_out_n = req_comp;
+ if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n))
+ return 0;
+ } else if (has_trans) {
+ // non-paletted image with tRNS -> source image has (constant) alpha
+ ++s->img_n;
+ }
+ STBI_FREE(z->expanded);
+ z->expanded = NULL;
+ return 1;
+ }
+
+ default:
+ // if critical, fail
+ if (first)
+ return stbi__err("first not IHDR", "Corrupt PNG");
+ if ((c.type & (1 << 29)) == 0) {
+#ifndef STBI_NO_FAILURE_STRINGS
+ // not threadsafe
+ static char invalid_chunk[] = "XXXX PNG chunk not known";
+ invalid_chunk[0] = STBI__BYTECAST(c.type >> 24);
+ invalid_chunk[1] = STBI__BYTECAST(c.type >> 16);
+ invalid_chunk[2] = STBI__BYTECAST(c.type >> 8);
+ invalid_chunk[3] = STBI__BYTECAST(c.type >> 0);
+#endif
+ return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type");
+ }
+ stbi__skip(s, c.length);
+ break;
+ }
+ // end of PNG chunk, read and skip CRC
+ stbi__get32be(s);
+ }
+}
+
+static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) {
+ void *result = NULL;
+ if (req_comp < 0 || req_comp > 4)
+ return stbi__errpuc("bad req_comp", "Internal error");
+ if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
+ if (p->depth < 8)
+ ri->bits_per_channel = 8;
+ else
+ ri->bits_per_channel = p->depth;
+ result = p->out;
+ p->out = NULL;
+ if (req_comp && req_comp != p->s->img_out_n) {
+ if (ri->bits_per_channel == 8)
+ result =
+ stbi__convert_format((unsigned char *)result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
+ else
+ result =
+ stbi__convert_format16((stbi__uint16 *)result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
+ p->s->img_out_n = req_comp;
+ if (result == NULL)
+ return result;
+ }
+ *x = p->s->img_x;
+ *y = p->s->img_y;
+ if (n)
+ *n = p->s->img_n;
+ }
+ STBI_FREE(p->out);
+ p->out = NULL;
+ STBI_FREE(p->expanded);
+ p->expanded = NULL;
+ STBI_FREE(p->idata);
+ p->idata = NULL;
+
+ return result;
+}
+
+static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) {
+ stbi__png p;
+ p.s = s;
+ return stbi__do_png(&p, x, y, comp, req_comp, ri);
+}
+
+static int stbi__png_test(stbi__context *s) {
+ int r;
+ r = stbi__check_png_header(s);
+ stbi__rewind(s);
+ return r;
+}
+
+static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) {
+ if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) {
+ stbi__rewind(p->s);
+ return 0;
+ }
+ if (x)
+ *x = p->s->img_x;
+ if (y)
+ *y = p->s->img_y;
+ if (comp)
+ *comp = p->s->img_n;
+ return 1;
+}
+
+static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) {
+ stbi__png p;
+ p.s = s;
+ return stbi__png_info_raw(&p, x, y, comp);
+}
+
+static int stbi__png_is16(stbi__context *s) {
+ stbi__png p;
+ p.s = s;
+ if (!stbi__png_info_raw(&p, NULL, NULL, NULL))
+ return 0;
+ if (p.depth != 16) {
+ stbi__rewind(p.s);
+ return 0;
+ }
+ return 1;
}
#endif
// Microsoft/Windows BMP image
#ifndef STBI_NO_BMP
-static int stbi__bmp_test_raw(stbi__context *s)
-{
- int r;
- int sz;
- if (stbi__get8(s) != 'B') return 0;
- if (stbi__get8(s) != 'M') return 0;
- stbi__get32le(s); // discard filesize
- stbi__get16le(s); // discard reserved
- stbi__get16le(s); // discard reserved
- stbi__get32le(s); // discard data offset
- sz = stbi__get32le(s);
- r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124);
- return r;
-}
-
-static int stbi__bmp_test(stbi__context *s)
-{
- int r = stbi__bmp_test_raw(s);
- stbi__rewind(s);
- return r;
+static int stbi__bmp_test_raw(stbi__context *s) {
+ int r;
+ int sz;
+ if (stbi__get8(s) != 'B')
+ return 0;
+ if (stbi__get8(s) != 'M')
+ return 0;
+ stbi__get32le(s); // discard filesize
+ stbi__get16le(s); // discard reserved
+ stbi__get16le(s); // discard reserved
+ stbi__get32le(s); // discard data offset
+ sz = stbi__get32le(s);
+ r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124);
+ return r;
+}
+
+static int stbi__bmp_test(stbi__context *s) {
+ int r = stbi__bmp_test_raw(s);
+ stbi__rewind(s);
+ return r;
}
-
// returns 0..31 for the highest set bit
-static int stbi__high_bit(unsigned int z)
-{
- int n=0;
- if (z == 0) return -1;
- if (z >= 0x10000) n += 16, z >>= 16;
- if (z >= 0x00100) n += 8, z >>= 8;
- if (z >= 0x00010) n += 4, z >>= 4;
- if (z >= 0x00004) n += 2, z >>= 2;
- if (z >= 0x00002) n += 1, z >>= 1;
- return n;
-}
-
-static int stbi__bitcount(unsigned int a)
-{
- a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2
- a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4
- a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits
- a = (a + (a >> 8)); // max 16 per 8 bits
- a = (a + (a >> 16)); // max 32 per 8 bits
- return a & 0xff;
+static int stbi__high_bit(unsigned int z) {
+ int n = 0;
+ if (z == 0)
+ return -1;
+ if (z >= 0x10000)
+ n += 16, z >>= 16;
+ if (z >= 0x00100)
+ n += 8, z >>= 8;
+ if (z >= 0x00010)
+ n += 4, z >>= 4;
+ if (z >= 0x00004)
+ n += 2, z >>= 2;
+ if (z >= 0x00002)
+ n += 1, z >>= 1;
+ return n;
+}
+
+static int stbi__bitcount(unsigned int a) {
+ a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2
+ a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4
+ a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits
+ a = (a + (a >> 8)); // max 16 per 8 bits
+ a = (a + (a >> 16)); // max 32 per 8 bits
+ return a & 0xff;
}
// extract an arbitrarily-aligned N-bit value (N=bits)
// from v, and then make it 8-bits long and fractionally
// extend it to full full range.
-static int stbi__shiftsigned(int v, int shift, int bits)
-{
- static unsigned int mul_table[9] = {
- 0,
- 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/,
- 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/,
- };
- static unsigned int shift_table[9] = {
- 0, 0,0,1,0,2,4,6,0,
- };
- if (shift < 0)
- v <<= -shift;
- else
- v >>= shift;
- STBI_ASSERT(v >= 0 && v < 256);
- v >>= (8-bits);
- STBI_ASSERT(bits >= 0 && bits <= 8);
- return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits];
-}
-
-typedef struct
-{
- int bpp, offset, hsz;
- unsigned int mr,mg,mb,ma, all_a;
+static int stbi__shiftsigned(int v, int shift, int bits) {
+ static unsigned int mul_table[9] = {
+ 0,
+ 0xff /*0b11111111*/,
+ 0x55 /*0b01010101*/,
+ 0x49 /*0b01001001*/,
+ 0x11 /*0b00010001*/,
+ 0x21 /*0b00100001*/,
+ 0x41 /*0b01000001*/,
+ 0x81 /*0b10000001*/,
+ 0x01 /*0b00000001*/,
+ };
+ static unsigned int shift_table[9] = {
+ 0, 0, 0, 1, 0, 2, 4, 6, 0,
+ };
+ if (shift < 0)
+ v <<= -shift;
+ else
+ v >>= shift;
+ STBI_ASSERT(v >= 0 && v < 256);
+ v >>= (8 - bits);
+ STBI_ASSERT(bits >= 0 && bits <= 8);
+ return (int)((unsigned)v * mul_table[bits]) >> shift_table[bits];
+}
+
+typedef struct {
+ int bpp, offset, hsz;
+ unsigned int mr, mg, mb, ma, all_a;
} stbi__bmp_data;
-static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
-{
- int hsz;
- if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP");
- stbi__get32le(s); // discard filesize
- stbi__get16le(s); // discard reserved
- stbi__get16le(s); // discard reserved
- info->offset = stbi__get32le(s);
- info->hsz = hsz = stbi__get32le(s);
- info->mr = info->mg = info->mb = info->ma = 0;
-
- if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
- if (hsz == 12) {
- s->img_x = stbi__get16le(s);
- s->img_y = stbi__get16le(s);
- } else {
- s->img_x = stbi__get32le(s);
- s->img_y = stbi__get32le(s);
- }
- if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP");
- info->bpp = stbi__get16le(s);
- if (hsz != 12) {
- int compress = stbi__get32le(s);
- if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
- stbi__get32le(s); // discard sizeof
- stbi__get32le(s); // discard hres
- stbi__get32le(s); // discard vres
- stbi__get32le(s); // discard colorsused
- stbi__get32le(s); // discard max important
- if (hsz == 40 || hsz == 56) {
- if (hsz == 56) {
- stbi__get32le(s);
- stbi__get32le(s);
- stbi__get32le(s);
- stbi__get32le(s);
- }
- if (info->bpp == 16 || info->bpp == 32) {
- if (compress == 0) {
- if (info->bpp == 32) {
- info->mr = 0xffu << 16;
- info->mg = 0xffu << 8;
- info->mb = 0xffu << 0;
- info->ma = 0xffu << 24;
- info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
- } else {
- info->mr = 31u << 10;
- info->mg = 31u << 5;
- info->mb = 31u << 0;
- }
- } else if (compress == 3) {
- info->mr = stbi__get32le(s);
- info->mg = stbi__get32le(s);
- info->mb = stbi__get32le(s);
- // not documented, but generated by photoshop and handled by mspaint
- if (info->mr == info->mg && info->mg == info->mb) {
- // ?!?!?
- return stbi__errpuc("bad BMP", "bad BMP");
- }
- } else
- return stbi__errpuc("bad BMP", "bad BMP");
- }
- } else {
- int i;
- if (hsz != 108 && hsz != 124)
- return stbi__errpuc("bad BMP", "bad BMP");
- info->mr = stbi__get32le(s);
- info->mg = stbi__get32le(s);
- info->mb = stbi__get32le(s);
- info->ma = stbi__get32le(s);
- stbi__get32le(s); // discard color space
- for (i=0; i < 12; ++i)
- stbi__get32le(s); // discard color space parameters
- if (hsz == 124) {
- stbi__get32le(s); // discard rendering intent
- stbi__get32le(s); // discard offset of profile data
- stbi__get32le(s); // discard size of profile data
- stbi__get32le(s); // discard reserved
- }
- }
- }
- return (void *) 1;
-}
-
-
-static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
-{
- stbi_uc *out;
- unsigned int mr=0,mg=0,mb=0,ma=0, all_a;
- stbi_uc pal[256][4];
- int psize=0,i,j,width;
- int flip_vertically, pad, target;
- stbi__bmp_data info;
- STBI_NOTUSED(ri);
-
- info.all_a = 255;
- if (stbi__bmp_parse_header(s, &info) == NULL)
- return NULL; // error code already set
-
- flip_vertically = ((int) s->img_y) > 0;
- s->img_y = abs((int) s->img_y);
-
- mr = info.mr;
- mg = info.mg;
- mb = info.mb;
- ma = info.ma;
- all_a = info.all_a;
-
- if (info.hsz == 12) {
- if (info.bpp < 24)
- psize = (info.offset - 14 - 24) / 3;
- } else {
- if (info.bpp < 16)
- psize = (info.offset - 14 - info.hsz) >> 2;
- }
-
- s->img_n = ma ? 4 : 3;
- if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
- target = req_comp;
- else
- target = s->img_n; // if they want monochrome, we'll post-convert
-
- // sanity-check size
- if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0))
- return stbi__errpuc("too large", "Corrupt BMP");
-
- out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0);
- if (!out) return stbi__errpuc("outofmem", "Out of memory");
- if (info.bpp < 16) {
- int z=0;
- if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); }
- for (i=0; i < psize; ++i) {
- pal[i][2] = stbi__get8(s);
- pal[i][1] = stbi__get8(s);
- pal[i][0] = stbi__get8(s);
- if (info.hsz != 12) stbi__get8(s);
- pal[i][3] = 255;
- }
- stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
- if (info.bpp == 1) width = (s->img_x + 7) >> 3;
- else if (info.bpp == 4) width = (s->img_x + 1) >> 1;
- else if (info.bpp == 8) width = s->img_x;
- else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); }
- pad = (-width)&3;
- if (info.bpp == 1) {
- for (j=0; j < (int) s->img_y; ++j) {
- int bit_offset = 7, v = stbi__get8(s);
- for (i=0; i < (int) s->img_x; ++i) {
- int color = (v>>bit_offset)&0x1;
- out[z++] = pal[color][0];
- out[z++] = pal[color][1];
- out[z++] = pal[color][2];
- if((--bit_offset) < 0) {
- bit_offset = 7;
- v = stbi__get8(s);
- }
- }
- stbi__skip(s, pad);
- }
- } else {
- for (j=0; j < (int) s->img_y; ++j) {
- for (i=0; i < (int) s->img_x; i += 2) {
- int v=stbi__get8(s),v2=0;
- if (info.bpp == 4) {
- v2 = v & 15;
- v >>= 4;
- }
- out[z++] = pal[v][0];
- out[z++] = pal[v][1];
- out[z++] = pal[v][2];
- if (target == 4) out[z++] = 255;
- if (i+1 == (int) s->img_x) break;
- v = (info.bpp == 8) ? stbi__get8(s) : v2;
- out[z++] = pal[v][0];
- out[z++] = pal[v][1];
- out[z++] = pal[v][2];
- if (target == 4) out[z++] = 255;
- }
- stbi__skip(s, pad);
- }
- }
- } else {
- int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
- int z = 0;
- int easy=0;
- stbi__skip(s, info.offset - 14 - info.hsz);
- if (info.bpp == 24) width = 3 * s->img_x;
- else if (info.bpp == 16) width = 2*s->img_x;
- else /* bpp = 32 and pad = 0 */ width=0;
- pad = (-width) & 3;
- if (info.bpp == 24) {
- easy = 1;
- } else if (info.bpp == 32) {
- if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
- easy = 2;
- }
- if (!easy) {
- if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }
- // right shift amt to put high bit in position #7
- rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr);
- gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg);
- bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb);
- ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma);
- }
- for (j=0; j < (int) s->img_y; ++j) {
- if (easy) {
- for (i=0; i < (int) s->img_x; ++i) {
- unsigned char a;
- out[z+2] = stbi__get8(s);
- out[z+1] = stbi__get8(s);
- out[z+0] = stbi__get8(s);
- z += 3;
- a = (easy == 2 ? stbi__get8(s) : 255);
- all_a |= a;
- if (target == 4) out[z++] = a;
- }
- } else {
- int bpp = info.bpp;
- for (i=0; i < (int) s->img_x; ++i) {
- stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));
- unsigned int a;
- out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount));
- out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount));
- out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount));
- a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255);
- all_a |= a;
- if (target == 4) out[z++] = STBI__BYTECAST(a);
- }
- }
- stbi__skip(s, pad);
- }
- }
-
- // if alpha channel is all 0s, replace with all 255s
- if (target == 4 && all_a == 0)
- for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4)
- out[i] = 255;
-
- if (flip_vertically) {
- stbi_uc t;
- for (j=0; j < (int) s->img_y>>1; ++j) {
- stbi_uc *p1 = out + j *s->img_x*target;
- stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target;
- for (i=0; i < (int) s->img_x*target; ++i) {
- t = p1[i], p1[i] = p2[i], p2[i] = t;
- }
- }
- }
-
- if (req_comp && req_comp != target) {
- out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y);
- if (out == NULL) return out; // stbi__convert_format frees input on failure
- }
-
- *x = s->img_x;
- *y = s->img_y;
- if (comp) *comp = s->img_n;
- return out;
+static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) {
+ int hsz;
+ if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M')
+ return stbi__errpuc("not BMP", "Corrupt BMP");
+ stbi__get32le(s); // discard filesize
+ stbi__get16le(s); // discard reserved
+ stbi__get16le(s); // discard reserved
+ info->offset = stbi__get32le(s);
+ info->hsz = hsz = stbi__get32le(s);
+ info->mr = info->mg = info->mb = info->ma = 0;
+
+ if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124)
+ return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
+ if (hsz == 12) {
+ s->img_x = stbi__get16le(s);
+ s->img_y = stbi__get16le(s);
+ } else {
+ s->img_x = stbi__get32le(s);
+ s->img_y = stbi__get32le(s);
+ }
+ if (stbi__get16le(s) != 1)
+ return stbi__errpuc("bad BMP", "bad BMP");
+ info->bpp = stbi__get16le(s);
+ if (hsz != 12) {
+ int compress = stbi__get32le(s);
+ if (compress == 1 || compress == 2)
+ return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
+ stbi__get32le(s); // discard sizeof
+ stbi__get32le(s); // discard hres
+ stbi__get32le(s); // discard vres
+ stbi__get32le(s); // discard colorsused
+ stbi__get32le(s); // discard max important
+ if (hsz == 40 || hsz == 56) {
+ if (hsz == 56) {
+ stbi__get32le(s);
+ stbi__get32le(s);
+ stbi__get32le(s);
+ stbi__get32le(s);
+ }
+ if (info->bpp == 16 || info->bpp == 32) {
+ if (compress == 0) {
+ if (info->bpp == 32) {
+ info->mr = 0xffu << 16;
+ info->mg = 0xffu << 8;
+ info->mb = 0xffu << 0;
+ info->ma = 0xffu << 24;
+ info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
+ } else {
+ info->mr = 31u << 10;
+ info->mg = 31u << 5;
+ info->mb = 31u << 0;
+ }
+ } else if (compress == 3) {
+ info->mr = stbi__get32le(s);
+ info->mg = stbi__get32le(s);
+ info->mb = stbi__get32le(s);
+ // not documented, but generated by photoshop and handled by mspaint
+ if (info->mr == info->mg && info->mg == info->mb) {
+ // ?!?!?
+ return stbi__errpuc("bad BMP", "bad BMP");
+ }
+ } else
+ return stbi__errpuc("bad BMP", "bad BMP");
+ }
+ } else {
+ int i;
+ if (hsz != 108 && hsz != 124)
+ return stbi__errpuc("bad BMP", "bad BMP");
+ info->mr = stbi__get32le(s);
+ info->mg = stbi__get32le(s);
+ info->mb = stbi__get32le(s);
+ info->ma = stbi__get32le(s);
+ stbi__get32le(s); // discard color space
+ for (i = 0; i < 12; ++i)
+ stbi__get32le(s); // discard color space parameters
+ if (hsz == 124) {
+ stbi__get32le(s); // discard rendering intent
+ stbi__get32le(s); // discard offset of profile data
+ stbi__get32le(s); // discard size of profile data
+ stbi__get32le(s); // discard reserved
+ }
+ }
+ }
+ return (void *)1;
+}
+
+static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) {
+ stbi_uc *out;
+ unsigned int mr = 0, mg = 0, mb = 0, ma = 0, all_a;
+ stbi_uc pal[256][4];
+ int psize = 0, i, j, width;
+ int flip_vertically, pad, target;
+ stbi__bmp_data info;
+ STBI_NOTUSED(ri);
+
+ info.all_a = 255;
+ if (stbi__bmp_parse_header(s, &info) == NULL)
+ return NULL; // error code already set
+
+ flip_vertically = ((int)s->img_y) > 0;
+ s->img_y = abs((int)s->img_y);
+
+ mr = info.mr;
+ mg = info.mg;
+ mb = info.mb;
+ ma = info.ma;
+ all_a = info.all_a;
+
+ if (info.hsz == 12) {
+ if (info.bpp < 24)
+ psize = (info.offset - 14 - 24) / 3;
+ } else {
+ if (info.bpp < 16)
+ psize = (info.offset - 14 - info.hsz) >> 2;
+ }
+
+ s->img_n = ma ? 4 : 3;
+ if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
+ target = req_comp;
+ else
+ target = s->img_n; // if they want monochrome, we'll post-convert
+
+ // sanity-check size
+ if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0))
+ return stbi__errpuc("too large", "Corrupt BMP");
+
+ out = (stbi_uc *)stbi__malloc_mad3(target, s->img_x, s->img_y, 0);
+ if (!out)
+ return stbi__errpuc("outofmem", "Out of memory");
+ if (info.bpp < 16) {
+ int z = 0;
+ if (psize == 0 || psize > 256) {
+ STBI_FREE(out);
+ return stbi__errpuc("invalid", "Corrupt BMP");
+ }
+ for (i = 0; i < psize; ++i) {
+ pal[i][2] = stbi__get8(s);
+ pal[i][1] = stbi__get8(s);
+ pal[i][0] = stbi__get8(s);
+ if (info.hsz != 12)
+ stbi__get8(s);
+ pal[i][3] = 255;
+ }
+ stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
+ if (info.bpp == 1)
+ width = (s->img_x + 7) >> 3;
+ else if (info.bpp == 4)
+ width = (s->img_x + 1) >> 1;
+ else if (info.bpp == 8)
+ width = s->img_x;
+ else {
+ STBI_FREE(out);
+ return stbi__errpuc("bad bpp", "Corrupt BMP");
+ }
+ pad = (-width) & 3;
+ if (info.bpp == 1) {
+ for (j = 0; j < (int)s->img_y; ++j) {
+ int bit_offset = 7, v = stbi__get8(s);
+ for (i = 0; i < (int)s->img_x; ++i) {
+ int color = (v >> bit_offset) & 0x1;
+ out[z++] = pal[color][0];
+ out[z++] = pal[color][1];
+ out[z++] = pal[color][2];
+ if ((--bit_offset) < 0) {
+ bit_offset = 7;
+ v = stbi__get8(s);
+ }
+ }
+ stbi__skip(s, pad);
+ }
+ } else {
+ for (j = 0; j < (int)s->img_y; ++j) {
+ for (i = 0; i < (int)s->img_x; i += 2) {
+ int v = stbi__get8(s), v2 = 0;
+ if (info.bpp == 4) {
+ v2 = v & 15;
+ v >>= 4;
+ }
+ out[z++] = pal[v][0];
+ out[z++] = pal[v][1];
+ out[z++] = pal[v][2];
+ if (target == 4)
+ out[z++] = 255;
+ if (i + 1 == (int)s->img_x)
+ break;
+ v = (info.bpp == 8) ? stbi__get8(s) : v2;
+ out[z++] = pal[v][0];
+ out[z++] = pal[v][1];
+ out[z++] = pal[v][2];
+ if (target == 4)
+ out[z++] = 255;
+ }
+ stbi__skip(s, pad);
+ }
+ }
+ } else {
+ int rshift = 0, gshift = 0, bshift = 0, ashift = 0, rcount = 0, gcount = 0, bcount = 0, acount = 0;
+ int z = 0;
+ int easy = 0;
+ stbi__skip(s, info.offset - 14 - info.hsz);
+ if (info.bpp == 24)
+ width = 3 * s->img_x;
+ else if (info.bpp == 16)
+ width = 2 * s->img_x;
+ else /* bpp = 32 and pad = 0 */
+ width = 0;
+ pad = (-width) & 3;
+ if (info.bpp == 24) {
+ easy = 1;
+ } else if (info.bpp == 32) {
+ if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
+ easy = 2;
+ }
+ if (!easy) {
+ if (!mr || !mg || !mb) {
+ STBI_FREE(out);
+ return stbi__errpuc("bad masks", "Corrupt BMP");
+ }
+ // right shift amt to put high bit in position #7
+ rshift = stbi__high_bit(mr) - 7;
+ rcount = stbi__bitcount(mr);
+ gshift = stbi__high_bit(mg) - 7;
+ gcount = stbi__bitcount(mg);
+ bshift = stbi__high_bit(mb) - 7;
+ bcount = stbi__bitcount(mb);
+ ashift = stbi__high_bit(ma) - 7;
+ acount = stbi__bitcount(ma);
+ }
+ for (j = 0; j < (int)s->img_y; ++j) {
+ if (easy) {
+ for (i = 0; i < (int)s->img_x; ++i) {
+ unsigned char a;
+ out[z + 2] = stbi__get8(s);
+ out[z + 1] = stbi__get8(s);
+ out[z + 0] = stbi__get8(s);
+ z += 3;
+ a = (easy == 2 ? stbi__get8(s) : 255);
+ all_a |= a;
+ if (target == 4)
+ out[z++] = a;
+ }
+ } else {
+ int bpp = info.bpp;
+ for (i = 0; i < (int)s->img_x; ++i) {
+ stbi__uint32 v = (bpp == 16 ? (stbi__uint32)stbi__get16le(s) : stbi__get32le(s));
+ unsigned int a;
+ out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount));
+ out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount));
+ out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount));
+ a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255);
+ all_a |= a;
+ if (target == 4)
+ out[z++] = STBI__BYTECAST(a);
+ }
+ }
+ stbi__skip(s, pad);
+ }
+ }
+
+ // if alpha channel is all 0s, replace with all 255s
+ if (target == 4 && all_a == 0)
+ for (i = 4 * s->img_x * s->img_y - 1; i >= 0; i -= 4)
+ out[i] = 255;
+
+ if (flip_vertically) {
+ stbi_uc t;
+ for (j = 0; j < (int)s->img_y >> 1; ++j) {
+ stbi_uc *p1 = out + j * s->img_x * target;
+ stbi_uc *p2 = out + (s->img_y - 1 - j) * s->img_x * target;
+ for (i = 0; i < (int)s->img_x * target; ++i) {
+ t = p1[i], p1[i] = p2[i], p2[i] = t;
+ }
+ }
+ }
+
+ if (req_comp && req_comp != target) {
+ out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y);
+ if (out == NULL)
+ return out; // stbi__convert_format frees input on failure
+ }
+
+ *x = s->img_x;
+ *y = s->img_y;
+ if (comp)
+ *comp = s->img_n;
+ return out;
}
#endif
// by Jonathan Dummer
#ifndef STBI_NO_TGA
// returns STBI_rgb or whatever, 0 on error
-static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16)
-{
- // only RGB or RGBA (incl. 16bit) or grey allowed
- if (is_rgb16) *is_rgb16 = 0;
- switch(bits_per_pixel) {
- case 8: return STBI_grey;
- case 16: if(is_grey) return STBI_grey_alpha;
- // fallthrough
- case 15: if(is_rgb16) *is_rgb16 = 1;
- return STBI_rgb;
- case 24: // fallthrough
- case 32: return bits_per_pixel/8;
- default: return 0;
- }
-}
-
-static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
-{
- int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
- int sz, tga_colormap_type;
- stbi__get8(s); // discard Offset
- tga_colormap_type = stbi__get8(s); // colormap type
- if( tga_colormap_type > 1 ) {
- stbi__rewind(s);
- return 0; // only RGB or indexed allowed
- }
- tga_image_type = stbi__get8(s); // image type
- if ( tga_colormap_type == 1 ) { // colormapped (paletted) image
- if (tga_image_type != 1 && tga_image_type != 9) {
- stbi__rewind(s);
- return 0;
- }
- stbi__skip(s,4); // skip index of first colormap entry and number of entries
- sz = stbi__get8(s); // check bits per palette color entry
- if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) {
- stbi__rewind(s);
- return 0;
- }
- stbi__skip(s,4); // skip image x and y origin
- tga_colormap_bpp = sz;
- } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE
- if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) {
- stbi__rewind(s);
- return 0; // only RGB or grey allowed, +/- RLE
- }
- stbi__skip(s,9); // skip colormap specification and image x/y origin
- tga_colormap_bpp = 0;
- }
- tga_w = stbi__get16le(s);
- if( tga_w < 1 ) {
- stbi__rewind(s);
- return 0; // test width
- }
- tga_h = stbi__get16le(s);
- if( tga_h < 1 ) {
- stbi__rewind(s);
- return 0; // test height
- }
- tga_bits_per_pixel = stbi__get8(s); // bits per pixel
- stbi__get8(s); // ignore alpha bits
- if (tga_colormap_bpp != 0) {
- if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
- // when using a colormap, tga_bits_per_pixel is the size of the indexes
- // I don't think anything but 8 or 16bit indexes makes sense
- stbi__rewind(s);
- return 0;
- }
- tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL);
- } else {
- tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL);
- }
- if(!tga_comp) {
- stbi__rewind(s);
- return 0;
- }
- if (x) *x = tga_w;
- if (y) *y = tga_h;
- if (comp) *comp = tga_comp;
- return 1; // seems to have passed everything
-}
-
-static int stbi__tga_test(stbi__context *s)
-{
- int res = 0;
- int sz, tga_color_type;
- stbi__get8(s); // discard Offset
- tga_color_type = stbi__get8(s); // color type
- if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed
- sz = stbi__get8(s); // image type
- if ( tga_color_type == 1 ) { // colormapped (paletted) image
- if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9
- stbi__skip(s,4); // skip index of first colormap entry and number of entries
- sz = stbi__get8(s); // check bits per palette color entry
- if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
- stbi__skip(s,4); // skip image x and y origin
- } else { // "normal" image w/o colormap
- if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE
- stbi__skip(s,9); // skip colormap specification and image x/y origin
- }
- if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width
- if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height
- sz = stbi__get8(s); // bits per pixel
- if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index
- if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
-
- res = 1; // if we got this far, everything's good and we can return 1 instead of 0
+static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int *is_rgb16) {
+ // only RGB or RGBA (incl. 16bit) or grey allowed
+ if (is_rgb16)
+ *is_rgb16 = 0;
+ switch (bits_per_pixel) {
+ case 8:
+ return STBI_grey;
+ case 16:
+ if (is_grey)
+ return STBI_grey_alpha;
+ // fallthrough
+ case 15:
+ if (is_rgb16)
+ *is_rgb16 = 1;
+ return STBI_rgb;
+ case 24: // fallthrough
+ case 32:
+ return bits_per_pixel / 8;
+ default:
+ return 0;
+ }
+}
+
+static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) {
+ int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
+ int sz, tga_colormap_type;
+ stbi__get8(s); // discard Offset
+ tga_colormap_type = stbi__get8(s); // colormap type
+ if (tga_colormap_type > 1) {
+ stbi__rewind(s);
+ return 0; // only RGB or indexed allowed
+ }
+ tga_image_type = stbi__get8(s); // image type
+ if (tga_colormap_type == 1) { // colormapped (paletted) image
+ if (tga_image_type != 1 && tga_image_type != 9) {
+ stbi__rewind(s);
+ return 0;
+ }
+ stbi__skip(s, 4); // skip index of first colormap entry and number of entries
+ sz = stbi__get8(s); // check bits per palette color entry
+ if ((sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32)) {
+ stbi__rewind(s);
+ return 0;
+ }
+ stbi__skip(s, 4); // skip image x and y origin
+ tga_colormap_bpp = sz;
+ } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE
+ if ((tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11)) {
+ stbi__rewind(s);
+ return 0; // only RGB or grey allowed, +/- RLE
+ }
+ stbi__skip(s, 9); // skip colormap specification and image x/y origin
+ tga_colormap_bpp = 0;
+ }
+ tga_w = stbi__get16le(s);
+ if (tga_w < 1) {
+ stbi__rewind(s);
+ return 0; // test width
+ }
+ tga_h = stbi__get16le(s);
+ if (tga_h < 1) {
+ stbi__rewind(s);
+ return 0; // test height
+ }
+ tga_bits_per_pixel = stbi__get8(s); // bits per pixel
+ stbi__get8(s); // ignore alpha bits
+ if (tga_colormap_bpp != 0) {
+ if ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
+ // when using a colormap, tga_bits_per_pixel is the size of the indexes
+ // I don't think anything but 8 or 16bit indexes makes sense
+ stbi__rewind(s);
+ return 0;
+ }
+ tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL);
+ } else {
+ tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL);
+ }
+ if (!tga_comp) {
+ stbi__rewind(s);
+ return 0;
+ }
+ if (x)
+ *x = tga_w;
+ if (y)
+ *y = tga_h;
+ if (comp)
+ *comp = tga_comp;
+ return 1; // seems to have passed everything
+}
+
+static int stbi__tga_test(stbi__context *s) {
+ int res = 0;
+ int sz, tga_color_type;
+ stbi__get8(s); // discard Offset
+ tga_color_type = stbi__get8(s); // color type
+ if (tga_color_type > 1)
+ goto errorEnd; // only RGB or indexed allowed
+ sz = stbi__get8(s); // image type
+ if (tga_color_type == 1) { // colormapped (paletted) image
+ if (sz != 1 && sz != 9)
+ goto errorEnd; // colortype 1 demands image type 1 or 9
+ stbi__skip(s, 4); // skip index of first colormap entry and number of entries
+ sz = stbi__get8(s); // check bits per palette color entry
+ if ((sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32))
+ goto errorEnd;
+ stbi__skip(s, 4); // skip image x and y origin
+ } else { // "normal" image w/o colormap
+ if ((sz != 2) && (sz != 3) && (sz != 10) && (sz != 11))
+ goto errorEnd; // only RGB or grey allowed, +/- RLE
+ stbi__skip(s, 9); // skip colormap specification and image x/y origin
+ }
+ if (stbi__get16le(s) < 1)
+ goto errorEnd; // test width
+ if (stbi__get16le(s) < 1)
+ goto errorEnd; // test height
+ sz = stbi__get8(s); // bits per pixel
+ if ((tga_color_type == 1) && (sz != 8) && (sz != 16))
+ goto errorEnd; // for colormapped images, bpp is size of an index
+ if ((sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32))
+ goto errorEnd;
+
+ res = 1; // if we got this far, everything's good and we can return 1 instead of 0
errorEnd:
- stbi__rewind(s);
- return res;
+ stbi__rewind(s);
+ return res;
}
// read 16bit value and convert to 24bit RGB
-static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
-{
- stbi__uint16 px = (stbi__uint16)stbi__get16le(s);
- stbi__uint16 fiveBitMask = 31;
- // we have 3 channels with 5bits each
- int r = (px >> 10) & fiveBitMask;
- int g = (px >> 5) & fiveBitMask;
- int b = px & fiveBitMask;
- // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later
- out[0] = (stbi_uc)((r * 255)/31);
- out[1] = (stbi_uc)((g * 255)/31);
- out[2] = (stbi_uc)((b * 255)/31);
-
- // some people claim that the most significant bit might be used for alpha
- // (possibly if an alpha-bit is set in the "image descriptor byte")
- // but that only made 16bit test images completely translucent..
- // so let's treat all 15 and 16bit TGAs as RGB with no alpha.
-}
-
-static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
-{
- // read in the TGA header stuff
- int tga_offset = stbi__get8(s);
- int tga_indexed = stbi__get8(s);
- int tga_image_type = stbi__get8(s);
- int tga_is_RLE = 0;
- int tga_palette_start = stbi__get16le(s);
- int tga_palette_len = stbi__get16le(s);
- int tga_palette_bits = stbi__get8(s);
- int tga_x_origin = stbi__get16le(s);
- int tga_y_origin = stbi__get16le(s);
- int tga_width = stbi__get16le(s);
- int tga_height = stbi__get16le(s);
- int tga_bits_per_pixel = stbi__get8(s);
- int tga_comp, tga_rgb16=0;
- int tga_inverted = stbi__get8(s);
- // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?)
- // image data
- unsigned char *tga_data;
- unsigned char *tga_palette = NULL;
- int i, j;
- unsigned char raw_data[4] = {0};
- int RLE_count = 0;
- int RLE_repeating = 0;
- int read_next_pixel = 1;
- STBI_NOTUSED(ri);
-
- // do a tiny bit of precessing
- if ( tga_image_type >= 8 )
- {
- tga_image_type -= 8;
- tga_is_RLE = 1;
- }
- tga_inverted = 1 - ((tga_inverted >> 5) & 1);
-
- // If I'm paletted, then I'll use the number of bits from the palette
- if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16);
- else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16);
-
- if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency
- return stbi__errpuc("bad format", "Can't find out TGA pixelformat");
-
- // tga info
- *x = tga_width;
- *y = tga_height;
- if (comp) *comp = tga_comp;
-
- if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0))
- return stbi__errpuc("too large", "Corrupt TGA");
-
- tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);
- if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
-
- // skip to the data's starting position (offset usually = 0)
- stbi__skip(s, tga_offset );
-
- if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) {
- for (i=0; i < tga_height; ++i) {
- int row = tga_inverted ? tga_height -i - 1 : i;
- stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;
- stbi__getn(s, tga_row, tga_width * tga_comp);
- }
- } else {
- // do I need to load a palette?
- if ( tga_indexed)
- {
- // any data to skip? (offset usually = 0)
- stbi__skip(s, tga_palette_start );
- // load the palette
- tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
- if (!tga_palette) {
- STBI_FREE(tga_data);
- return stbi__errpuc("outofmem", "Out of memory");
- }
- if (tga_rgb16) {
- stbi_uc *pal_entry = tga_palette;
- STBI_ASSERT(tga_comp == STBI_rgb);
- for (i=0; i < tga_palette_len; ++i) {
- stbi__tga_read_rgb16(s, pal_entry);
- pal_entry += tga_comp;
- }
- } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {
- STBI_FREE(tga_data);
- STBI_FREE(tga_palette);
- return stbi__errpuc("bad palette", "Corrupt TGA");
- }
- }
- // load the data
- for (i=0; i < tga_width * tga_height; ++i)
- {
- // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk?
- if ( tga_is_RLE )
- {
- if ( RLE_count == 0 )
- {
- // yep, get the next byte as a RLE command
- int RLE_cmd = stbi__get8(s);
- RLE_count = 1 + (RLE_cmd & 127);
- RLE_repeating = RLE_cmd >> 7;
- read_next_pixel = 1;
- } else if ( !RLE_repeating )
- {
- read_next_pixel = 1;
- }
- } else
- {
- read_next_pixel = 1;
- }
- // OK, if I need to read a pixel, do it now
- if ( read_next_pixel )
- {
- // load however much data we did have
- if ( tga_indexed )
- {
- // read in index, then perform the lookup
- int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);
- if ( pal_idx >= tga_palette_len ) {
- // invalid index
- pal_idx = 0;
- }
- pal_idx *= tga_comp;
- for (j = 0; j < tga_comp; ++j) {
- raw_data[j] = tga_palette[pal_idx+j];
- }
- } else if(tga_rgb16) {
- STBI_ASSERT(tga_comp == STBI_rgb);
- stbi__tga_read_rgb16(s, raw_data);
- } else {
- // read in the data raw
- for (j = 0; j < tga_comp; ++j) {
- raw_data[j] = stbi__get8(s);
- }
- }
- // clear the reading flag for the next pixel
- read_next_pixel = 0;
- } // end of reading a pixel
-
- // copy data
- for (j = 0; j < tga_comp; ++j)
- tga_data[i*tga_comp+j] = raw_data[j];
-
- // in case we're in RLE mode, keep counting down
- --RLE_count;
- }
- // do I need to invert the image?
- if ( tga_inverted )
- {
- for (j = 0; j*2 < tga_height; ++j)
- {
- int index1 = j * tga_width * tga_comp;
- int index2 = (tga_height - 1 - j) * tga_width * tga_comp;
- for (i = tga_width * tga_comp; i > 0; --i)
- {
- unsigned char temp = tga_data[index1];
- tga_data[index1] = tga_data[index2];
- tga_data[index2] = temp;
- ++index1;
- ++index2;
- }
- }
- }
- // clear my palette, if I had one
- if ( tga_palette != NULL )
- {
- STBI_FREE( tga_palette );
- }
- }
-
- // swap RGB - if the source data was RGB16, it already is in the right order
- if (tga_comp >= 3 && !tga_rgb16)
- {
- unsigned char* tga_pixel = tga_data;
- for (i=0; i < tga_width * tga_height; ++i)
- {
- unsigned char temp = tga_pixel[0];
- tga_pixel[0] = tga_pixel[2];
- tga_pixel[2] = temp;
- tga_pixel += tga_comp;
- }
- }
-
- // convert to target component count
- if (req_comp && req_comp != tga_comp)
- tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height);
-
- // the things I do to get rid of an error message, and yet keep
- // Microsoft's C compilers happy... [8^(
- tga_palette_start = tga_palette_len = tga_palette_bits =
- tga_x_origin = tga_y_origin = 0;
- // OK, done
- return tga_data;
+static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc *out) {
+ stbi__uint16 px = (stbi__uint16)stbi__get16le(s);
+ stbi__uint16 fiveBitMask = 31;
+ // we have 3 channels with 5bits each
+ int r = (px >> 10) & fiveBitMask;
+ int g = (px >> 5) & fiveBitMask;
+ int b = px & fiveBitMask;
+ // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later
+ out[0] = (stbi_uc)((r * 255) / 31);
+ out[1] = (stbi_uc)((g * 255) / 31);
+ out[2] = (stbi_uc)((b * 255) / 31);
+
+ // some people claim that the most significant bit might be used for alpha
+ // (possibly if an alpha-bit is set in the "image descriptor byte")
+ // but that only made 16bit test images completely translucent..
+ // so let's treat all 15 and 16bit TGAs as RGB with no alpha.
+}
+
+static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) {
+ // read in the TGA header stuff
+ int tga_offset = stbi__get8(s);
+ int tga_indexed = stbi__get8(s);
+ int tga_image_type = stbi__get8(s);
+ int tga_is_RLE = 0;
+ int tga_palette_start = stbi__get16le(s);
+ int tga_palette_len = stbi__get16le(s);
+ int tga_palette_bits = stbi__get8(s);
+ int tga_x_origin = stbi__get16le(s);
+ int tga_y_origin = stbi__get16le(s);
+ int tga_width = stbi__get16le(s);
+ int tga_height = stbi__get16le(s);
+ int tga_bits_per_pixel = stbi__get8(s);
+ int tga_comp, tga_rgb16 = 0;
+ int tga_inverted = stbi__get8(s);
+ // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?)
+ // image data
+ unsigned char *tga_data;
+ unsigned char *tga_palette = NULL;
+ int i, j;
+ unsigned char raw_data[4] = {0};
+ int RLE_count = 0;
+ int RLE_repeating = 0;
+ int read_next_pixel = 1;
+ STBI_NOTUSED(ri);
+
+ // do a tiny bit of precessing
+ if (tga_image_type >= 8) {
+ tga_image_type -= 8;
+ tga_is_RLE = 1;
+ }
+ tga_inverted = 1 - ((tga_inverted >> 5) & 1);
+
+ // If I'm paletted, then I'll use the number of bits from the palette
+ if (tga_indexed)
+ tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16);
+ else
+ tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16);
+
+ if (!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency
+ return stbi__errpuc("bad format", "Can't find out TGA pixelformat");
+
+ // tga info
+ *x = tga_width;
+ *y = tga_height;
+ if (comp)
+ *comp = tga_comp;
+
+ if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0))
+ return stbi__errpuc("too large", "Corrupt TGA");
+
+ tga_data = (unsigned char *)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);
+ if (!tga_data)
+ return stbi__errpuc("outofmem", "Out of memory");
+
+ // skip to the data's starting position (offset usually = 0)
+ stbi__skip(s, tga_offset);
+
+ if (!tga_indexed && !tga_is_RLE && !tga_rgb16) {
+ for (i = 0; i < tga_height; ++i) {
+ int row = tga_inverted ? tga_height - i - 1 : i;
+ stbi_uc *tga_row = tga_data + row * tga_width * tga_comp;
+ stbi__getn(s, tga_row, tga_width * tga_comp);
+ }
+ } else {
+ // do I need to load a palette?
+ if (tga_indexed) {
+ // any data to skip? (offset usually = 0)
+ stbi__skip(s, tga_palette_start);
+ // load the palette
+ tga_palette = (unsigned char *)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
+ if (!tga_palette) {
+ STBI_FREE(tga_data);
+ return stbi__errpuc("outofmem", "Out of memory");
+ }
+ if (tga_rgb16) {
+ stbi_uc *pal_entry = tga_palette;
+ STBI_ASSERT(tga_comp == STBI_rgb);
+ for (i = 0; i < tga_palette_len; ++i) {
+ stbi__tga_read_rgb16(s, pal_entry);
+ pal_entry += tga_comp;
+ }
+ } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {
+ STBI_FREE(tga_data);
+ STBI_FREE(tga_palette);
+ return stbi__errpuc("bad palette", "Corrupt TGA");
+ }
+ }
+ // load the data
+ for (i = 0; i < tga_width * tga_height; ++i) {
+ // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk?
+ if (tga_is_RLE) {
+ if (RLE_count == 0) {
+ // yep, get the next byte as a RLE command
+ int RLE_cmd = stbi__get8(s);
+ RLE_count = 1 + (RLE_cmd & 127);
+ RLE_repeating = RLE_cmd >> 7;
+ read_next_pixel = 1;
+ } else if (!RLE_repeating) {
+ read_next_pixel = 1;
+ }
+ } else {
+ read_next_pixel = 1;
+ }
+ // OK, if I need to read a pixel, do it now
+ if (read_next_pixel) {
+ // load however much data we did have
+ if (tga_indexed) {
+ // read in index, then perform the lookup
+ int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);
+ if (pal_idx >= tga_palette_len) {
+ // invalid index
+ pal_idx = 0;
+ }
+ pal_idx *= tga_comp;
+ for (j = 0; j < tga_comp; ++j) {
+ raw_data[j] = tga_palette[pal_idx + j];
+ }
+ } else if (tga_rgb16) {
+ STBI_ASSERT(tga_comp == STBI_rgb);
+ stbi__tga_read_rgb16(s, raw_data);
+ } else {
+ // read in the data raw
+ for (j = 0; j < tga_comp; ++j) {
+ raw_data[j] = stbi__get8(s);
+ }
+ }
+ // clear the reading flag for the next pixel
+ read_next_pixel = 0;
+ } // end of reading a pixel
+
+ // copy data
+ for (j = 0; j < tga_comp; ++j)
+ tga_data[i * tga_comp + j] = raw_data[j];
+
+ // in case we're in RLE mode, keep counting down
+ --RLE_count;
+ }
+ // do I need to invert the image?
+ if (tga_inverted) {
+ for (j = 0; j * 2 < tga_height; ++j) {
+ int index1 = j * tga_width * tga_comp;
+ int index2 = (tga_height - 1 - j) * tga_width * tga_comp;
+ for (i = tga_width * tga_comp; i > 0; --i) {
+ unsigned char temp = tga_data[index1];
+ tga_data[index1] = tga_data[index2];
+ tga_data[index2] = temp;
+ ++index1;
+ ++index2;
+ }
+ }
+ }
+ // clear my palette, if I had one
+ if (tga_palette != NULL) {
+ STBI_FREE(tga_palette);
+ }
+ }
+
+ // swap RGB - if the source data was RGB16, it already is in the right order
+ if (tga_comp >= 3 && !tga_rgb16) {
+ unsigned char *tga_pixel = tga_data;
+ for (i = 0; i < tga_width * tga_height; ++i) {
+ unsigned char temp = tga_pixel[0];
+ tga_pixel[0] = tga_pixel[2];
+ tga_pixel[2] = temp;
+ tga_pixel += tga_comp;
+ }
+ }
+
+ // convert to target component count
+ if (req_comp && req_comp != tga_comp)
+ tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height);
+
+ // the things I do to get rid of an error message, and yet keep
+ // Microsoft's C compilers happy... [8^(
+ tga_palette_start = tga_palette_len = tga_palette_bits = tga_x_origin = tga_y_origin = 0;
+ // OK, done
+ return tga_data;
}
#endif
// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB
#ifndef STBI_NO_PSD
-static int stbi__psd_test(stbi__context *s)
-{
- int r = (stbi__get32be(s) == 0x38425053);
- stbi__rewind(s);
- return r;
-}
-
-static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount)
-{
- int count, nleft, len;
-
- count = 0;
- while ((nleft = pixelCount - count) > 0) {
- len = stbi__get8(s);
- if (len == 128) {
- // No-op.
- } else if (len < 128) {
- // Copy next len+1 bytes literally.
- len++;
- if (len > nleft) return 0; // corrupt data
- count += len;
- while (len) {
- *p = stbi__get8(s);
- p += 4;
- len--;
- }
- } else if (len > 128) {
- stbi_uc val;
- // Next -len+1 bytes in the dest are replicated from next source byte.
- // (Interpret len as a negative 8-bit int.)
- len = 257 - len;
- if (len > nleft) return 0; // corrupt data
- val = stbi__get8(s);
- count += len;
- while (len) {
- *p = val;
- p += 4;
- len--;
- }
- }
- }
-
- return 1;
-}
-
-static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
-{
- int pixelCount;
- int channelCount, compression;
- int channel, i;
- int bitdepth;
- int w,h;
- stbi_uc *out;
- STBI_NOTUSED(ri);
-
- // Check identifier
- if (stbi__get32be(s) != 0x38425053) // "8BPS"
- return stbi__errpuc("not PSD", "Corrupt PSD image");
-
- // Check file type version.
- if (stbi__get16be(s) != 1)
- return stbi__errpuc("wrong version", "Unsupported version of PSD image");
-
- // Skip 6 reserved bytes.
- stbi__skip(s, 6 );
-
- // Read the number of channels (R, G, B, A, etc).
- channelCount = stbi__get16be(s);
- if (channelCount < 0 || channelCount > 16)
- return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image");
-
- // Read the rows and columns of the image.
- h = stbi__get32be(s);
- w = stbi__get32be(s);
-
- // Make sure the depth is 8 bits.
- bitdepth = stbi__get16be(s);
- if (bitdepth != 8 && bitdepth != 16)
- return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit");
-
- // Make sure the color mode is RGB.
- // Valid options are:
- // 0: Bitmap
- // 1: Grayscale
- // 2: Indexed color
- // 3: RGB color
- // 4: CMYK color
- // 7: Multichannel
- // 8: Duotone
- // 9: Lab color
- if (stbi__get16be(s) != 3)
- return stbi__errpuc("wrong color format", "PSD is not in RGB color format");
-
- // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.)
- stbi__skip(s,stbi__get32be(s) );
-
- // Skip the image resources. (resolution, pen tool paths, etc)
- stbi__skip(s, stbi__get32be(s) );
-
- // Skip the reserved data.
- stbi__skip(s, stbi__get32be(s) );
-
- // Find out if the data is compressed.
- // Known values:
- // 0: no compression
- // 1: RLE compressed
- compression = stbi__get16be(s);
- if (compression > 1)
- return stbi__errpuc("bad compression", "PSD has an unknown compression format");
-
- // Check size
- if (!stbi__mad3sizes_valid(4, w, h, 0))
- return stbi__errpuc("too large", "Corrupt PSD");
-
- // Create the destination image.
-
- if (!compression && bitdepth == 16 && bpc == 16) {
- out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0);
- ri->bits_per_channel = 16;
- } else
- out = (stbi_uc *) stbi__malloc(4 * w*h);
-
- if (!out) return stbi__errpuc("outofmem", "Out of memory");
- pixelCount = w*h;
-
- // Initialize the data to zero.
- //memset( out, 0, pixelCount * 4 );
-
- // Finally, the image data.
- if (compression) {
- // RLE as used by .PSD and .TIFF
- // Loop until you get the number of unpacked bytes you are expecting:
- // Read the next source byte into n.
- // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
- // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.
- // Else if n is 128, noop.
- // Endloop
-
- // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data,
- // which we're going to just skip.
- stbi__skip(s, h * channelCount * 2 );
-
- // Read the RLE data by channel.
- for (channel = 0; channel < 4; channel++) {
- stbi_uc *p;
-
- p = out+channel;
- if (channel >= channelCount) {
- // Fill this channel with default data.
- for (i = 0; i < pixelCount; i++, p += 4)
- *p = (channel == 3 ? 255 : 0);
- } else {
- // Read the RLE data.
- if (!stbi__psd_decode_rle(s, p, pixelCount)) {
- STBI_FREE(out);
- return stbi__errpuc("corrupt", "bad RLE data");
- }
- }
- }
-
- } else {
- // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...)
- // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image.
-
- // Read the data by channel.
- for (channel = 0; channel < 4; channel++) {
- if (channel >= channelCount) {
- // Fill this channel with default data.
- if (bitdepth == 16 && bpc == 16) {
- stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
- stbi__uint16 val = channel == 3 ? 65535 : 0;
- for (i = 0; i < pixelCount; i++, q += 4)
- *q = val;
- } else {
- stbi_uc *p = out+channel;
- stbi_uc val = channel == 3 ? 255 : 0;
- for (i = 0; i < pixelCount; i++, p += 4)
- *p = val;
- }
- } else {
- if (ri->bits_per_channel == 16) { // output bpc
- stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
- for (i = 0; i < pixelCount; i++, q += 4)
- *q = (stbi__uint16) stbi__get16be(s);
- } else {
- stbi_uc *p = out+channel;
- if (bitdepth == 16) { // input bpc
- for (i = 0; i < pixelCount; i++, p += 4)
- *p = (stbi_uc) (stbi__get16be(s) >> 8);
- } else {
- for (i = 0; i < pixelCount; i++, p += 4)
- *p = stbi__get8(s);
- }
- }
- }
- }
- }
-
- // remove weird white matte from PSD
- if (channelCount >= 4) {
- if (ri->bits_per_channel == 16) {
- for (i=0; i < w*h; ++i) {
- stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i;
- if (pixel[3] != 0 && pixel[3] != 65535) {
- float a = pixel[3] / 65535.0f;
- float ra = 1.0f / a;
- float inv_a = 65535.0f * (1 - ra);
- pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a);
- pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a);
- pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a);
- }
- }
- } else {
- for (i=0; i < w*h; ++i) {
- unsigned char *pixel = out + 4*i;
- if (pixel[3] != 0 && pixel[3] != 255) {
- float a = pixel[3] / 255.0f;
- float ra = 1.0f / a;
- float inv_a = 255.0f * (1 - ra);
- pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);
- pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);
- pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);
- }
- }
- }
- }
-
- // convert to desired output format
- if (req_comp && req_comp != 4) {
- if (ri->bits_per_channel == 16)
- out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h);
- else
- out = stbi__convert_format(out, 4, req_comp, w, h);
- if (out == NULL) return out; // stbi__convert_format frees input on failure
- }
-
- if (comp) *comp = 4;
- *y = h;
- *x = w;
-
- return out;
+static int stbi__psd_test(stbi__context *s) {
+ int r = (stbi__get32be(s) == 0x38425053);
+ stbi__rewind(s);
+ return r;
+}
+
+static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) {
+ int count, nleft, len;
+
+ count = 0;
+ while ((nleft = pixelCount - count) > 0) {
+ len = stbi__get8(s);
+ if (len == 128) {
+ // No-op.
+ } else if (len < 128) {
+ // Copy next len+1 bytes literally.
+ len++;
+ if (len > nleft)
+ return 0; // corrupt data
+ count += len;
+ while (len) {
+ *p = stbi__get8(s);
+ p += 4;
+ len--;
+ }
+ } else if (len > 128) {
+ stbi_uc val;
+ // Next -len+1 bytes in the dest are replicated from next source byte.
+ // (Interpret len as a negative 8-bit int.)
+ len = 257 - len;
+ if (len > nleft)
+ return 0; // corrupt data
+ val = stbi__get8(s);
+ count += len;
+ while (len) {
+ *p = val;
+ p += 4;
+ len--;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) {
+ int pixelCount;
+ int channelCount, compression;
+ int channel, i;
+ int bitdepth;
+ int w, h;
+ stbi_uc *out;
+ STBI_NOTUSED(ri);
+
+ // Check identifier
+ if (stbi__get32be(s) != 0x38425053) // "8BPS"
+ return stbi__errpuc("not PSD", "Corrupt PSD image");
+
+ // Check file type version.
+ if (stbi__get16be(s) != 1)
+ return stbi__errpuc("wrong version", "Unsupported version of PSD image");
+
+ // Skip 6 reserved bytes.
+ stbi__skip(s, 6);
+
+ // Read the number of channels (R, G, B, A, etc).
+ channelCount = stbi__get16be(s);
+ if (channelCount < 0 || channelCount > 16)
+ return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image");
+
+ // Read the rows and columns of the image.
+ h = stbi__get32be(s);
+ w = stbi__get32be(s);
+
+ // Make sure the depth is 8 bits.
+ bitdepth = stbi__get16be(s);
+ if (bitdepth != 8 && bitdepth != 16)
+ return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit");
+
+ // Make sure the color mode is RGB.
+ // Valid options are:
+ // 0: Bitmap
+ // 1: Grayscale
+ // 2: Indexed color
+ // 3: RGB color
+ // 4: CMYK color
+ // 7: Multichannel
+ // 8: Duotone
+ // 9: Lab color
+ if (stbi__get16be(s) != 3)
+ return stbi__errpuc("wrong color format", "PSD is not in RGB color format");
+
+ // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.)
+ stbi__skip(s, stbi__get32be(s));
+
+ // Skip the image resources. (resolution, pen tool paths, etc)
+ stbi__skip(s, stbi__get32be(s));
+
+ // Skip the reserved data.
+ stbi__skip(s, stbi__get32be(s));
+
+ // Find out if the data is compressed.
+ // Known values:
+ // 0: no compression
+ // 1: RLE compressed
+ compression = stbi__get16be(s);
+ if (compression > 1)
+ return stbi__errpuc("bad compression", "PSD has an unknown compression format");
+
+ // Check size
+ if (!stbi__mad3sizes_valid(4, w, h, 0))
+ return stbi__errpuc("too large", "Corrupt PSD");
+
+ // Create the destination image.
+
+ if (!compression && bitdepth == 16 && bpc == 16) {
+ out = (stbi_uc *)stbi__malloc_mad3(8, w, h, 0);
+ ri->bits_per_channel = 16;
+ } else
+ out = (stbi_uc *)stbi__malloc(4 * w * h);
+
+ if (!out)
+ return stbi__errpuc("outofmem", "Out of memory");
+ pixelCount = w * h;
+
+ // Initialize the data to zero.
+ // memset( out, 0, pixelCount * 4 );
+
+ // Finally, the image data.
+ if (compression) {
+ // RLE as used by .PSD and .TIFF
+ // Loop until you get the number of unpacked bytes you are expecting:
+ // Read the next source byte into n.
+ // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
+ // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.
+ // Else if n is 128, noop.
+ // Endloop
+
+ // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data,
+ // which we're going to just skip.
+ stbi__skip(s, h * channelCount * 2);
+
+ // Read the RLE data by channel.
+ for (channel = 0; channel < 4; channel++) {
+ stbi_uc *p;
+
+ p = out + channel;
+ if (channel >= channelCount) {
+ // Fill this channel with default data.
+ for (i = 0; i < pixelCount; i++, p += 4)
+ *p = (channel == 3 ? 255 : 0);
+ } else {
+ // Read the RLE data.
+ if (!stbi__psd_decode_rle(s, p, pixelCount)) {
+ STBI_FREE(out);
+ return stbi__errpuc("corrupt", "bad RLE data");
+ }
+ }
+ }
+
+ } else {
+ // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...)
+ // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image.
+
+ // Read the data by channel.
+ for (channel = 0; channel < 4; channel++) {
+ if (channel >= channelCount) {
+ // Fill this channel with default data.
+ if (bitdepth == 16 && bpc == 16) {
+ stbi__uint16 *q = ((stbi__uint16 *)out) + channel;
+ stbi__uint16 val = channel == 3 ? 65535 : 0;
+ for (i = 0; i < pixelCount; i++, q += 4)
+ *q = val;
+ } else {
+ stbi_uc *p = out + channel;
+ stbi_uc val = channel == 3 ? 255 : 0;
+ for (i = 0; i < pixelCount; i++, p += 4)
+ *p = val;
+ }
+ } else {
+ if (ri->bits_per_channel == 16) { // output bpc
+ stbi__uint16 *q = ((stbi__uint16 *)out) + channel;
+ for (i = 0; i < pixelCount; i++, q += 4)
+ *q = (stbi__uint16)stbi__get16be(s);
+ } else {
+ stbi_uc *p = out + channel;
+ if (bitdepth == 16) { // input bpc
+ for (i = 0; i < pixelCount; i++, p += 4)
+ *p = (stbi_uc)(stbi__get16be(s) >> 8);
+ } else {
+ for (i = 0; i < pixelCount; i++, p += 4)
+ *p = stbi__get8(s);
+ }
+ }
+ }
+ }
+ }
+
+ // remove weird white matte from PSD
+ if (channelCount >= 4) {
+ if (ri->bits_per_channel == 16) {
+ for (i = 0; i < w * h; ++i) {
+ stbi__uint16 *pixel = (stbi__uint16 *)out + 4 * i;
+ if (pixel[3] != 0 && pixel[3] != 65535) {
+ float a = pixel[3] / 65535.0f;
+ float ra = 1.0f / a;
+ float inv_a = 65535.0f * (1 - ra);
+ pixel[0] = (stbi__uint16)(pixel[0] * ra + inv_a);
+ pixel[1] = (stbi__uint16)(pixel[1] * ra + inv_a);
+ pixel[2] = (stbi__uint16)(pixel[2] * ra + inv_a);
+ }
+ }
+ } else {
+ for (i = 0; i < w * h; ++i) {
+ unsigned char *pixel = out + 4 * i;
+ if (pixel[3] != 0 && pixel[3] != 255) {
+ float a = pixel[3] / 255.0f;
+ float ra = 1.0f / a;
+ float inv_a = 255.0f * (1 - ra);
+ pixel[0] = (unsigned char)(pixel[0] * ra + inv_a);
+ pixel[1] = (unsigned char)(pixel[1] * ra + inv_a);
+ pixel[2] = (unsigned char)(pixel[2] * ra + inv_a);
+ }
+ }
+ }
+ }
+
+ // convert to desired output format
+ if (req_comp && req_comp != 4) {
+ if (ri->bits_per_channel == 16)
+ out = (stbi_uc *)stbi__convert_format16((stbi__uint16 *)out, 4, req_comp, w, h);
+ else
+ out = stbi__convert_format(out, 4, req_comp, w, h);
+ if (out == NULL)
+ return out; // stbi__convert_format frees input on failure
+ }
+
+ if (comp)
+ *comp = 4;
+ *y = h;
+ *x = w;
+
+ return out;
}
#endif
// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/
#ifndef STBI_NO_PIC
-static int stbi__pic_is4(stbi__context *s,const char *str)
-{
- int i;
- for (i=0; i<4; ++i)
- if (stbi__get8(s) != (stbi_uc)str[i])
- return 0;
+static int stbi__pic_is4(stbi__context *s, const char *str) {
+ int i;
+ for (i = 0; i < 4; ++i)
+ if (stbi__get8(s) != (stbi_uc)str[i])
+ return 0;
- return 1;
+ return 1;
}
-static int stbi__pic_test_core(stbi__context *s)
-{
- int i;
+static int stbi__pic_test_core(stbi__context *s) {
+ int i;
- if (!stbi__pic_is4(s,"\x53\x80\xF6\x34"))
- return 0;
+ if (!stbi__pic_is4(s, "\x53\x80\xF6\x34"))
+ return 0;
- for(i=0;i<84;++i)
- stbi__get8(s);
+ for (i = 0; i < 84; ++i)
+ stbi__get8(s);
- if (!stbi__pic_is4(s,"PICT"))
- return 0;
+ if (!stbi__pic_is4(s, "PICT"))
+ return 0;
- return 1;
+ return 1;
}
-typedef struct
-{
- stbi_uc size,type,channel;
+typedef struct {
+ stbi_uc size, type, channel;
} stbi__pic_packet;
-static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest)
-{
- int mask=0x80, i;
+static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) {
+ int mask = 0x80, i;
- for (i=0; i<4; ++i, mask>>=1) {
- if (channel & mask) {
- if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short");
- dest[i]=stbi__get8(s);
- }
- }
+ for (i = 0; i < 4; ++i, mask >>= 1) {
+ if (channel & mask) {
+ if (stbi__at_eof(s))
+ return stbi__errpuc("bad file", "PIC file too short");
+ dest[i] = stbi__get8(s);
+ }
+ }
- return dest;
+ return dest;
}
-static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src)
-{
- int mask=0x80,i;
+static void stbi__copyval(int channel, stbi_uc *dest, const stbi_uc *src) {
+ int mask = 0x80, i;
- for (i=0;i<4; ++i, mask>>=1)
- if (channel&mask)
- dest[i]=src[i];
+ for (i = 0; i < 4; ++i, mask >>= 1)
+ if (channel & mask)
+ dest[i] = src[i];
}
-static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result)
-{
- int act_comp=0,num_packets=0,y,chained;
- stbi__pic_packet packets[10];
-
- // this will (should...) cater for even some bizarre stuff like having data
- // for the same channel in multiple packets.
- do {
- stbi__pic_packet *packet;
-
- if (num_packets==sizeof(packets)/sizeof(packets[0]))
- return stbi__errpuc("bad format","too many packets");
-
- packet = &packets[num_packets++];
+static stbi_uc *stbi__pic_load_core(stbi__context *s, int width, int height, int *comp, stbi_uc *result) {
+ int act_comp = 0, num_packets = 0, y, chained;
+ stbi__pic_packet packets[10];
- chained = stbi__get8(s);
- packet->size = stbi__get8(s);
- packet->type = stbi__get8(s);
- packet->channel = stbi__get8(s);
+ // this will (should...) cater for even some bizarre stuff like having data
+ // for the same channel in multiple packets.
+ do {
+ stbi__pic_packet *packet;
+
+ if (num_packets == sizeof(packets) / sizeof(packets[0]))
+ return stbi__errpuc("bad format", "too many packets");
- act_comp |= packet->channel;
+ packet = &packets[num_packets++];
- if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)");
- if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp");
- } while (chained);
+ chained = stbi__get8(s);
+ packet->size = stbi__get8(s);
+ packet->type = stbi__get8(s);
+ packet->channel = stbi__get8(s);
- *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel?
+ act_comp |= packet->channel;
- for(y=0; y<height; ++y) {
- int packet_idx;
+ if (stbi__at_eof(s))
+ return stbi__errpuc("bad file", "file too short (reading packets)");
+ if (packet->size != 8)
+ return stbi__errpuc("bad format", "packet isn't 8bpp");
+ } while (chained);
- for(packet_idx=0; packet_idx < num_packets; ++packet_idx) {
- stbi__pic_packet *packet = &packets[packet_idx];
- stbi_uc *dest = result+y*width*4;
+ *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel?
- switch (packet->type) {
- default:
- return stbi__errpuc("bad format","packet has bad compression type");
+ for (y = 0; y < height; ++y) {
+ int packet_idx;
- case 0: {//uncompressed
- int x;
+ for (packet_idx = 0; packet_idx < num_packets; ++packet_idx) {
+ stbi__pic_packet *packet = &packets[packet_idx];
+ stbi_uc *dest = result + y * width * 4;
- for(x=0;x<width;++x, dest+=4)
- if (!stbi__readval(s,packet->channel,dest))
- return 0;
- break;
- }
+ switch (packet->type) {
+ default:
+ return stbi__errpuc("bad format", "packet has bad compression type");
- case 1://Pure RLE
- {
- int left=width, i;
+ case 0: { // uncompressed
+ int x;
- while (left>0) {
- stbi_uc count,value[4];
+ for (x = 0; x < width; ++x, dest += 4)
+ if (!stbi__readval(s, packet->channel, dest))
+ return 0;
+ break;
+ }
+
+ case 1: // Pure RLE
+ {
+ int left = width, i;
- count=stbi__get8(s);
- if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)");
+ while (left > 0) {
+ stbi_uc count, value[4];
- if (count > left)
- count = (stbi_uc) left;
+ count = stbi__get8(s);
+ if (stbi__at_eof(s))
+ return stbi__errpuc("bad file", "file too short (pure read count)");
- if (!stbi__readval(s,packet->channel,value)) return 0;
+ if (count > left)
+ count = (stbi_uc)left;
- for(i=0; i<count; ++i,dest+=4)
- stbi__copyval(packet->channel,dest,value);
- left -= count;
- }
- }
- break;
+ if (!stbi__readval(s, packet->channel, value))
+ return 0;
- case 2: {//Mixed RLE
- int left=width;
- while (left>0) {
- int count = stbi__get8(s), i;
- if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)");
+ for (i = 0; i < count; ++i, dest += 4)
+ stbi__copyval(packet->channel, dest, value);
+ left -= count;
+ }
+ } break;
- if (count >= 128) { // Repeated
- stbi_uc value[4];
+ case 2: { // Mixed RLE
+ int left = width;
+ while (left > 0) {
+ int count = stbi__get8(s), i;
+ if (stbi__at_eof(s))
+ return stbi__errpuc("bad file", "file too short (mixed read count)");
+
+ if (count >= 128) { // Repeated
+ stbi_uc value[4];
+
+ if (count == 128)
+ count = stbi__get16be(s);
+ else
+ count -= 127;
+ if (count > left)
+ return stbi__errpuc("bad file", "scanline overrun");
- if (count==128)
- count = stbi__get16be(s);
- else
- count -= 127;
- if (count > left)
- return stbi__errpuc("bad file","scanline overrun");
+ if (!stbi__readval(s, packet->channel, value))
+ return 0;
- if (!stbi__readval(s,packet->channel,value))
- return 0;
-
- for(i=0;i<count;++i, dest += 4)
- stbi__copyval(packet->channel,dest,value);
- } else { // Raw
- ++count;
- if (count>left) return stbi__errpuc("bad file","scanline overrun");
-
- for(i=0;i<count;++i, dest+=4)
- if (!stbi__readval(s,packet->channel,dest))
- return 0;
- }
- left-=count;
- }
- break;
- }
- }
- }
- }
-
- return result;
-}
-
-static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri)
-{
- stbi_uc *result;
- int i, x,y, internal_comp;
- STBI_NOTUSED(ri);
-
- if (!comp) comp = &internal_comp;
-
- for (i=0; i<92; ++i)
- stbi__get8(s);
-
- x = stbi__get16be(s);
- y = stbi__get16be(s);
- if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)");
- if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
-
- stbi__get32be(s); //skip `ratio'
- stbi__get16be(s); //skip `fields'
- stbi__get16be(s); //skip `pad'
-
- // intermediate buffer is RGBA
- result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0);
- memset(result, 0xff, x*y*4);
-
- if (!stbi__pic_load_core(s,x,y,comp, result)) {
- STBI_FREE(result);
- result=0;
- }
- *px = x;
- *py = y;
- if (req_comp == 0) req_comp = *comp;
- result=stbi__convert_format(result,4,req_comp,x,y);
-
- return result;
-}
-
-static int stbi__pic_test(stbi__context *s)
-{
- int r = stbi__pic_test_core(s);
- stbi__rewind(s);
- return r;
+ for (i = 0; i < count; ++i, dest += 4)
+ stbi__copyval(packet->channel, dest, value);
+ } else { // Raw
+ ++count;
+ if (count > left)
+ return stbi__errpuc("bad file", "scanline overrun");
+
+ for (i = 0; i < count; ++i, dest += 4)
+ if (!stbi__readval(s, packet->channel, dest))
+ return 0;
+ }
+ left -= count;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+static void *stbi__pic_load(stbi__context *s, int *px, int *py, int *comp, int req_comp, stbi__result_info *ri) {
+ stbi_uc *result;
+ int i, x, y, internal_comp;
+ STBI_NOTUSED(ri);
+
+ if (!comp)
+ comp = &internal_comp;
+
+ for (i = 0; i < 92; ++i)
+ stbi__get8(s);
+
+ x = stbi__get16be(s);
+ y = stbi__get16be(s);
+ if (stbi__at_eof(s))
+ return stbi__errpuc("bad file", "file too short (pic header)");
+ if (!stbi__mad3sizes_valid(x, y, 4, 0))
+ return stbi__errpuc("too large", "PIC image too large to decode");
+
+ stbi__get32be(s); // skip `ratio'
+ stbi__get16be(s); // skip `fields'
+ stbi__get16be(s); // skip `pad'
+
+ // intermediate buffer is RGBA
+ result = (stbi_uc *)stbi__malloc_mad3(x, y, 4, 0);
+ memset(result, 0xff, x * y * 4);
+
+ if (!stbi__pic_load_core(s, x, y, comp, result)) {
+ STBI_FREE(result);
+ result = 0;
+ }
+ *px = x;
+ *py = y;
+ if (req_comp == 0)
+ req_comp = *comp;
+ result = stbi__convert_format(result, 4, req_comp, x, y);
+
+ return result;
+}
+
+static int stbi__pic_test(stbi__context *s) {
+ int r = stbi__pic_test_core(s);
+ stbi__rewind(s);
+ return r;
}
#endif
// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb
#ifndef STBI_NO_GIF
-typedef struct
-{
- stbi__int16 prefix;
- stbi_uc first;
- stbi_uc suffix;
+typedef struct {
+ stbi__int16 prefix;
+ stbi_uc first;
+ stbi_uc suffix;
} stbi__gif_lzw;
-typedef struct
-{
- int w,h;
- stbi_uc *out; // output buffer (always 4 components)
- stbi_uc *background; // The current "background" as far as a gif is concerned
- stbi_uc *history;
- int flags, bgindex, ratio, transparent, eflags;
- stbi_uc pal[256][4];
- stbi_uc lpal[256][4];
- stbi__gif_lzw codes[8192];
- stbi_uc *color_table;
- int parse, step;
- int lflags;
- int start_x, start_y;
- int max_x, max_y;
- int cur_x, cur_y;
- int line_size;
- int delay;
+typedef struct {
+ int w, h;
+ stbi_uc *out; // output buffer (always 4 components)
+ stbi_uc *background; // The current "background" as far as a gif is concerned
+ stbi_uc *history;
+ int flags, bgindex, ratio, transparent, eflags;
+ stbi_uc pal[256][4];
+ stbi_uc lpal[256][4];
+ stbi__gif_lzw codes[8192];
+ stbi_uc *color_table;
+ int parse, step;
+ int lflags;
+ int start_x, start_y;
+ int max_x, max_y;
+ int cur_x, cur_y;
+ int line_size;
+ int delay;
} stbi__gif;
-static int stbi__gif_test_raw(stbi__context *s)
-{
- int sz;
- if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0;
- sz = stbi__get8(s);
- if (sz != '9' && sz != '7') return 0;
- if (stbi__get8(s) != 'a') return 0;
- return 1;
-}
-
-static int stbi__gif_test(stbi__context *s)
-{
- int r = stbi__gif_test_raw(s);
- stbi__rewind(s);
- return r;
-}
-
-static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp)
-{
- int i;
- for (i=0; i < num_entries; ++i) {
- pal[i][2] = stbi__get8(s);
- pal[i][1] = stbi__get8(s);
- pal[i][0] = stbi__get8(s);
- pal[i][3] = transp == i ? 0 : 255;
- }
-}
-
-static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info)
-{
- stbi_uc version;
- if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8')
- return stbi__err("not GIF", "Corrupt GIF");
-
- version = stbi__get8(s);
- if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF");
- if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF");
-
- stbi__g_failure_reason = "";
- g->w = stbi__get16le(s);
- g->h = stbi__get16le(s);
- g->flags = stbi__get8(s);
- g->bgindex = stbi__get8(s);
- g->ratio = stbi__get8(s);
- g->transparent = -1;
-
- if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments
-
- if (is_info) return 1;
-
- if (g->flags & 0x80)
- stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1);
-
- return 1;
-}
-
-static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
-{
- stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
- if (!stbi__gif_header(s, g, comp, 1)) {
- STBI_FREE(g);
- stbi__rewind( s );
- return 0;
- }
- if (x) *x = g->w;
- if (y) *y = g->h;
- STBI_FREE(g);
- return 1;
-}
-
-static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)
-{
- stbi_uc *p, *c;
- int idx;
-
- // recurse to decode the prefixes, since the linked-list is backwards,
- // and working backwards through an interleaved image would be nasty
- if (g->codes[code].prefix >= 0)
- stbi__out_gif_code(g, g->codes[code].prefix);
-
- if (g->cur_y >= g->max_y) return;
-
- idx = g->cur_x + g->cur_y;
- p = &g->out[idx];
- g->history[idx / 4] = 1;
-
- c = &g->color_table[g->codes[code].suffix * 4];
- if (c[3] > 128) { // don't render transparent pixels;
- p[0] = c[2];
- p[1] = c[1];
- p[2] = c[0];
- p[3] = c[3];
- }
- g->cur_x += 4;
-
- if (g->cur_x >= g->max_x) {
- g->cur_x = g->start_x;
- g->cur_y += g->step;
-
- while (g->cur_y >= g->max_y && g->parse > 0) {
- g->step = (1 << g->parse) * g->line_size;
- g->cur_y = g->start_y + (g->step >> 1);
- --g->parse;
- }
- }
-}
-
-static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g)
-{
- stbi_uc lzw_cs;
- stbi__int32 len, init_code;
- stbi__uint32 first;
- stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear;
- stbi__gif_lzw *p;
-
- lzw_cs = stbi__get8(s);
- if (lzw_cs > 12) return NULL;
- clear = 1 << lzw_cs;
- first = 1;
- codesize = lzw_cs + 1;
- codemask = (1 << codesize) - 1;
- bits = 0;
- valid_bits = 0;
- for (init_code = 0; init_code < clear; init_code++) {
- g->codes[init_code].prefix = -1;
- g->codes[init_code].first = (stbi_uc) init_code;
- g->codes[init_code].suffix = (stbi_uc) init_code;
- }
-
- // support no starting clear code
- avail = clear+2;
- oldcode = -1;
-
- len = 0;
- for(;;) {
- if (valid_bits < codesize) {
- if (len == 0) {
- len = stbi__get8(s); // start new block
- if (len == 0)
- return g->out;
- }
- --len;
- bits |= (stbi__int32) stbi__get8(s) << valid_bits;
- valid_bits += 8;
- } else {
- stbi__int32 code = bits & codemask;
- bits >>= codesize;
- valid_bits -= codesize;
- // @OPTIMIZE: is there some way we can accelerate the non-clear path?
- if (code == clear) { // clear code
- codesize = lzw_cs + 1;
- codemask = (1 << codesize) - 1;
- avail = clear + 2;
- oldcode = -1;
- first = 0;
- } else if (code == clear + 1) { // end of stream code
- stbi__skip(s, len);
- while ((len = stbi__get8(s)) > 0)
- stbi__skip(s,len);
- return g->out;
- } else if (code <= avail) {
- if (first) {
- return stbi__errpuc("no clear code", "Corrupt GIF");
- }
-
- if (oldcode >= 0) {
- p = &g->codes[avail++];
- if (avail > 8192) {
- return stbi__errpuc("too many codes", "Corrupt GIF");
- }
-
- p->prefix = (stbi__int16) oldcode;
- p->first = g->codes[oldcode].first;
- p->suffix = (code == avail) ? p->first : g->codes[code].first;
- } else if (code == avail)
- return stbi__errpuc("illegal code in raster", "Corrupt GIF");
-
- stbi__out_gif_code(g, (stbi__uint16) code);
-
- if ((avail & codemask) == 0 && avail <= 0x0FFF) {
- codesize++;
- codemask = (1 << codesize) - 1;
- }
-
- oldcode = code;
- } else {
- return stbi__errpuc("illegal code in raster", "Corrupt GIF");
- }
- }
- }
+static int stbi__gif_test_raw(stbi__context *s) {
+ int sz;
+ if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8')
+ return 0;
+ sz = stbi__get8(s);
+ if (sz != '9' && sz != '7')
+ return 0;
+ if (stbi__get8(s) != 'a')
+ return 0;
+ return 1;
+}
+
+static int stbi__gif_test(stbi__context *s) {
+ int r = stbi__gif_test_raw(s);
+ stbi__rewind(s);
+ return r;
+}
+
+static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) {
+ int i;
+ for (i = 0; i < num_entries; ++i) {
+ pal[i][2] = stbi__get8(s);
+ pal[i][1] = stbi__get8(s);
+ pal[i][0] = stbi__get8(s);
+ pal[i][3] = transp == i ? 0 : 255;
+ }
+}
+
+static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) {
+ stbi_uc version;
+ if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8')
+ return stbi__err("not GIF", "Corrupt GIF");
+
+ version = stbi__get8(s);
+ if (version != '7' && version != '9')
+ return stbi__err("not GIF", "Corrupt GIF");
+ if (stbi__get8(s) != 'a')
+ return stbi__err("not GIF", "Corrupt GIF");
+
+ stbi__g_failure_reason = "";
+ g->w = stbi__get16le(s);
+ g->h = stbi__get16le(s);
+ g->flags = stbi__get8(s);
+ g->bgindex = stbi__get8(s);
+ g->ratio = stbi__get8(s);
+ g->transparent = -1;
+
+ if (comp != 0)
+ *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments
+
+ if (is_info)
+ return 1;
+
+ if (g->flags & 0x80)
+ stbi__gif_parse_colortable(s, g->pal, 2 << (g->flags & 7), -1);
+
+ return 1;
+}
+
+static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) {
+ stbi__gif *g = (stbi__gif *)stbi__malloc(sizeof(stbi__gif));
+ if (!stbi__gif_header(s, g, comp, 1)) {
+ STBI_FREE(g);
+ stbi__rewind(s);
+ return 0;
+ }
+ if (x)
+ *x = g->w;
+ if (y)
+ *y = g->h;
+ STBI_FREE(g);
+ return 1;
+}
+
+static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) {
+ stbi_uc *p, *c;
+ int idx;
+
+ // recurse to decode the prefixes, since the linked-list is backwards,
+ // and working backwards through an interleaved image would be nasty
+ if (g->codes[code].prefix >= 0)
+ stbi__out_gif_code(g, g->codes[code].prefix);
+
+ if (g->cur_y >= g->max_y)
+ return;
+
+ idx = g->cur_x + g->cur_y;
+ p = &g->out[idx];
+ g->history[idx / 4] = 1;
+
+ c = &g->color_table[g->codes[code].suffix * 4];
+ if (c[3] > 128) { // don't render transparent pixels;
+ p[0] = c[2];
+ p[1] = c[1];
+ p[2] = c[0];
+ p[3] = c[3];
+ }
+ g->cur_x += 4;
+
+ if (g->cur_x >= g->max_x) {
+ g->cur_x = g->start_x;
+ g->cur_y += g->step;
+
+ while (g->cur_y >= g->max_y && g->parse > 0) {
+ g->step = (1 << g->parse) * g->line_size;
+ g->cur_y = g->start_y + (g->step >> 1);
+ --g->parse;
+ }
+ }
+}
+
+static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) {
+ stbi_uc lzw_cs;
+ stbi__int32 len, init_code;
+ stbi__uint32 first;
+ stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear;
+ stbi__gif_lzw *p;
+
+ lzw_cs = stbi__get8(s);
+ if (lzw_cs > 12)
+ return NULL;
+ clear = 1 << lzw_cs;
+ first = 1;
+ codesize = lzw_cs + 1;
+ codemask = (1 << codesize) - 1;
+ bits = 0;
+ valid_bits = 0;
+ for (init_code = 0; init_code < clear; init_code++) {
+ g->codes[init_code].prefix = -1;
+ g->codes[init_code].first = (stbi_uc)init_code;
+ g->codes[init_code].suffix = (stbi_uc)init_code;
+ }
+
+ // support no starting clear code
+ avail = clear + 2;
+ oldcode = -1;
+
+ len = 0;
+ for (;;) {
+ if (valid_bits < codesize) {
+ if (len == 0) {
+ len = stbi__get8(s); // start new block
+ if (len == 0)
+ return g->out;
+ }
+ --len;
+ bits |= (stbi__int32)stbi__get8(s) << valid_bits;
+ valid_bits += 8;
+ } else {
+ stbi__int32 code = bits & codemask;
+ bits >>= codesize;
+ valid_bits -= codesize;
+ // @OPTIMIZE: is there some way we can accelerate the non-clear path?
+ if (code == clear) { // clear code
+ codesize = lzw_cs + 1;
+ codemask = (1 << codesize) - 1;
+ avail = clear + 2;
+ oldcode = -1;
+ first = 0;
+ } else if (code == clear + 1) { // end of stream code
+ stbi__skip(s, len);
+ while ((len = stbi__get8(s)) > 0)
+ stbi__skip(s, len);
+ return g->out;
+ } else if (code <= avail) {
+ if (first) {
+ return stbi__errpuc("no clear code", "Corrupt GIF");
+ }
+
+ if (oldcode >= 0) {
+ p = &g->codes[avail++];
+ if (avail > 8192) {
+ return stbi__errpuc("too many codes", "Corrupt GIF");
+ }
+
+ p->prefix = (stbi__int16)oldcode;
+ p->first = g->codes[oldcode].first;
+ p->suffix = (code == avail) ? p->first : g->codes[code].first;
+ } else if (code == avail)
+ return stbi__errpuc("illegal code in raster", "Corrupt GIF");
+
+ stbi__out_gif_code(g, (stbi__uint16)code);
+
+ if ((avail & codemask) == 0 && avail <= 0x0FFF) {
+ codesize++;
+ codemask = (1 << codesize) - 1;
+ }
+
+ oldcode = code;
+ } else {
+ return stbi__errpuc("illegal code in raster", "Corrupt GIF");
+ }
+ }
+ }
}
// this function is designed to support animated gifs, although stb_image doesn't support it
// two back is the image from two frames ago, used for a very specific disposal format
-static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back)
-{
- int dispose;
- int first_frame;
- int pi;
- int pcount;
-
- // on first frame, any non-written pixels get the background colour (non-transparent)
- first_frame = 0;
- if (g->out == 0) {
- if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header
- g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
- g->background = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
- g->history = (stbi_uc *) stbi__malloc(g->w * g->h);
- if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
-
- // image is treated as "tranparent" at the start - ie, nothing overwrites the current background;
- // background colour is only used for pixels that are not rendered first frame, after that "background"
- // color refers to teh color that was there the previous frame.
- memset( g->out, 0x00, 4 * g->w * g->h );
- memset( g->background, 0x00, 4 * g->w * g->h ); // state of the background (starts transparent)
- memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame
- first_frame = 1;
- } else {
- // second frame - how do we dispoase of the previous one?
- dispose = (g->eflags & 0x1C) >> 2;
- pcount = g->w * g->h;
-
- if ((dispose == 3) && (two_back == 0)) {
- dispose = 2; // if I don't have an image to revert back to, default to the old background
- }
-
- if (dispose == 3) { // use previous graphic
- for (pi = 0; pi < pcount; ++pi) {
- if (g->history[pi]) {
- memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 );
- }
- }
- } else if (dispose == 2) {
- // restore what was changed last frame to background before that frame;
- for (pi = 0; pi < pcount; ++pi) {
- if (g->history[pi]) {
- memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 );
- }
- }
- } else {
- // This is a non-disposal case eithe way, so just
- // leave the pixels as is, and they will become the new background
- // 1: do not dispose
- // 0: not specified.
- }
-
- // background is what out is after the undoing of the previou frame;
- memcpy( g->background, g->out, 4 * g->w * g->h );
- }
-
- // clear my history;
- memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame
-
- for (;;) {
- int tag = stbi__get8(s);
- switch (tag) {
- case 0x2C: /* Image Descriptor */
- {
- stbi__int32 x, y, w, h;
- stbi_uc *o;
-
- x = stbi__get16le(s);
- y = stbi__get16le(s);
- w = stbi__get16le(s);
- h = stbi__get16le(s);
- if (((x + w) > (g->w)) || ((y + h) > (g->h)))
- return stbi__errpuc("bad Image Descriptor", "Corrupt GIF");
-
- g->line_size = g->w * 4;
- g->start_x = x * 4;
- g->start_y = y * g->line_size;
- g->max_x = g->start_x + w * 4;
- g->max_y = g->start_y + h * g->line_size;
- g->cur_x = g->start_x;
- g->cur_y = g->start_y;
-
- g->lflags = stbi__get8(s);
-
- if (g->lflags & 0x40) {
- g->step = 8 * g->line_size; // first interlaced spacing
- g->parse = 3;
- } else {
- g->step = g->line_size;
- g->parse = 0;
- }
-
- if (g->lflags & 0x80) {
- stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1);
- g->color_table = (stbi_uc *) g->lpal;
- } else if (g->flags & 0x80) {
- g->color_table = (stbi_uc *) g->pal;
- } else
- return stbi__errpuc("missing color table", "Corrupt GIF");
-
- o = stbi__process_gif_raster(s, g);
- if (o == NULL) return NULL;
-
- // if this was the first frame,
- pcount = g->w * g->h;
- if (first_frame && (g->bgindex > 0)) {
- // if first frame, any pixel not drawn to gets the background color
- for (pi = 0; pi < pcount; ++pi) {
- if (g->history[pi] == 0) {
- g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be;
- memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 );
- }
- }
- }
-
- return o;
- }
-
- case 0x21: // Comment Extension.
- {
- int len;
- int ext = stbi__get8(s);
- if (ext == 0xF9) { // Graphic Control Extension.
- len = stbi__get8(s);
- if (len == 4) {
- g->eflags = stbi__get8(s);
- g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths.
-
- // unset old transparent
- if (g->transparent >= 0) {
- g->pal[g->transparent][3] = 255;
- }
- if (g->eflags & 0x01) {
- g->transparent = stbi__get8(s);
- if (g->transparent >= 0) {
- g->pal[g->transparent][3] = 0;
- }
- } else {
- // don't need transparent
- stbi__skip(s, 1);
- g->transparent = -1;
- }
- } else {
- stbi__skip(s, len);
- break;
- }
- }
- while ((len = stbi__get8(s)) != 0) {
- stbi__skip(s, len);
- }
- break;
- }
-
- case 0x3B: // gif stream termination code
- return (stbi_uc *) s; // using '1' causes warning on some compilers
-
- default:
- return stbi__errpuc("unknown code", "Corrupt GIF");
- }
- }
-}
-
-static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
-{
- if (stbi__gif_test(s)) {
- int layers = 0;
- stbi_uc *u = 0;
- stbi_uc *out = 0;
- stbi_uc *two_back = 0;
- stbi__gif g;
- int stride;
- memset(&g, 0, sizeof(g));
- if (delays) {
- *delays = 0;
- }
-
- do {
- u = stbi__gif_load_next(s, &g, comp, req_comp, two_back);
- if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
-
- if (u) {
- *x = g.w;
- *y = g.h;
- ++layers;
- stride = g.w * g.h * 4;
-
- if (out) {
- out = (stbi_uc*) STBI_REALLOC( out, layers * stride );
- if (delays) {
- *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers );
- }
- } else {
- out = (stbi_uc*)stbi__malloc( layers * stride );
- if (delays) {
- *delays = (int*) stbi__malloc( layers * sizeof(int) );
- }
- }
- memcpy( out + ((layers - 1) * stride), u, stride );
- if (layers >= 2) {
- two_back = out - 2 * stride;
- }
-
- if (delays) {
- (*delays)[layers - 1U] = g.delay;
- }
- }
- } while (u != 0);
-
- // free temp buffer;
- STBI_FREE(g.out);
- STBI_FREE(g.history);
- STBI_FREE(g.background);
-
- // do the final conversion after loading everything;
- if (req_comp && req_comp != 4)
- out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h);
-
- *z = layers;
- return out;
- } else {
- return stbi__errpuc("not GIF", "Image was not as a gif type.");
- }
-}
-
-static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
-{
- stbi_uc *u = 0;
- stbi__gif g;
- memset(&g, 0, sizeof(g));
-
- u = stbi__gif_load_next(s, &g, comp, req_comp, 0);
- if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
- if (u) {
- *x = g.w;
- *y = g.h;
-
- // moved conversion to after successful load so that the same
- // can be done for multiple frames.
- if (req_comp && req_comp != 4)
- u = stbi__convert_format(u, 4, req_comp, g.w, g.h);
- }
-
- // free buffers needed for multiple frame loading;
- STBI_FREE(g.history);
- STBI_FREE(g.background);
-
- return u;
-}
-
-static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp)
-{
- return stbi__gif_info_raw(s,x,y,comp);
-}
+static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) {
+ int dispose;
+ int first_frame;
+ int pi;
+ int pcount;
+
+ // on first frame, any non-written pixels get the background colour (non-transparent)
+ first_frame = 0;
+ if (g->out == 0) {
+ if (!stbi__gif_header(s, g, comp, 0))
+ return 0; // stbi__g_failure_reason set by stbi__gif_header
+ g->out = (stbi_uc *)stbi__malloc(4 * g->w * g->h);
+ g->background = (stbi_uc *)stbi__malloc(4 * g->w * g->h);
+ g->history = (stbi_uc *)stbi__malloc(g->w * g->h);
+ if (g->out == 0)
+ return stbi__errpuc("outofmem", "Out of memory");
+
+ // image is treated as "tranparent" at the start - ie, nothing overwrites the current background;
+ // background colour is only used for pixels that are not rendered first frame, after that "background"
+ // color refers to teh color that was there the previous frame.
+ memset(g->out, 0x00, 4 * g->w * g->h);
+ memset(g->background, 0x00, 4 * g->w * g->h); // state of the background (starts transparent)
+ memset(g->history, 0x00, g->w * g->h); // pixels that were affected previous frame
+ first_frame = 1;
+ } else {
+ // second frame - how do we dispoase of the previous one?
+ dispose = (g->eflags & 0x1C) >> 2;
+ pcount = g->w * g->h;
+
+ if ((dispose == 3) && (two_back == 0)) {
+ dispose = 2; // if I don't have an image to revert back to, default to the old background
+ }
+
+ if (dispose == 3) { // use previous graphic
+ for (pi = 0; pi < pcount; ++pi) {
+ if (g->history[pi]) {
+ memcpy(&g->out[pi * 4], &two_back[pi * 4], 4);
+ }
+ }
+ } else if (dispose == 2) {
+ // restore what was changed last frame to background before that frame;
+ for (pi = 0; pi < pcount; ++pi) {
+ if (g->history[pi]) {
+ memcpy(&g->out[pi * 4], &g->background[pi * 4], 4);
+ }
+ }
+ } else {
+ // This is a non-disposal case eithe way, so just
+ // leave the pixels as is, and they will become the new background
+ // 1: do not dispose
+ // 0: not specified.
+ }
+
+ // background is what out is after the undoing of the previou frame;
+ memcpy(g->background, g->out, 4 * g->w * g->h);
+ }
+
+ // clear my history;
+ memset(g->history, 0x00, g->w * g->h); // pixels that were affected previous frame
+
+ for (;;) {
+ int tag = stbi__get8(s);
+ switch (tag) {
+ case 0x2C: /* Image Descriptor */
+ {
+ stbi__int32 x, y, w, h;
+ stbi_uc *o;
+
+ x = stbi__get16le(s);
+ y = stbi__get16le(s);
+ w = stbi__get16le(s);
+ h = stbi__get16le(s);
+ if (((x + w) > (g->w)) || ((y + h) > (g->h)))
+ return stbi__errpuc("bad Image Descriptor", "Corrupt GIF");
+
+ g->line_size = g->w * 4;
+ g->start_x = x * 4;
+ g->start_y = y * g->line_size;
+ g->max_x = g->start_x + w * 4;
+ g->max_y = g->start_y + h * g->line_size;
+ g->cur_x = g->start_x;
+ g->cur_y = g->start_y;
+
+ g->lflags = stbi__get8(s);
+
+ if (g->lflags & 0x40) {
+ g->step = 8 * g->line_size; // first interlaced spacing
+ g->parse = 3;
+ } else {
+ g->step = g->line_size;
+ g->parse = 0;
+ }
+
+ if (g->lflags & 0x80) {
+ stbi__gif_parse_colortable(s, g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1);
+ g->color_table = (stbi_uc *)g->lpal;
+ } else if (g->flags & 0x80) {
+ g->color_table = (stbi_uc *)g->pal;
+ } else
+ return stbi__errpuc("missing color table", "Corrupt GIF");
+
+ o = stbi__process_gif_raster(s, g);
+ if (o == NULL)
+ return NULL;
+
+ // if this was the first frame,
+ pcount = g->w * g->h;
+ if (first_frame && (g->bgindex > 0)) {
+ // if first frame, any pixel not drawn to gets the background color
+ for (pi = 0; pi < pcount; ++pi) {
+ if (g->history[pi] == 0) {
+ g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be
+ // reset next frame if need be;
+ memcpy(&g->out[pi * 4], &g->pal[g->bgindex], 4);
+ }
+ }
+ }
+
+ return o;
+ }
+
+ case 0x21: // Comment Extension.
+ {
+ int len;
+ int ext = stbi__get8(s);
+ if (ext == 0xF9) { // Graphic Control Extension.
+ len = stbi__get8(s);
+ if (len == 4) {
+ g->eflags = stbi__get8(s);
+ g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths.
+
+ // unset old transparent
+ if (g->transparent >= 0) {
+ g->pal[g->transparent][3] = 255;
+ }
+ if (g->eflags & 0x01) {
+ g->transparent = stbi__get8(s);
+ if (g->transparent >= 0) {
+ g->pal[g->transparent][3] = 0;
+ }
+ } else {
+ // don't need transparent
+ stbi__skip(s, 1);
+ g->transparent = -1;
+ }
+ } else {
+ stbi__skip(s, len);
+ break;
+ }
+ }
+ while ((len = stbi__get8(s)) != 0) {
+ stbi__skip(s, len);
+ }
+ break;
+ }
+
+ case 0x3B: // gif stream termination code
+ return (stbi_uc *)s; // using '1' causes warning on some compilers
+
+ default:
+ return stbi__errpuc("unknown code", "Corrupt GIF");
+ }
+ }
+}
+
+static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) {
+ if (stbi__gif_test(s)) {
+ int layers = 0;
+ stbi_uc *u = 0;
+ stbi_uc *out = 0;
+ stbi_uc *two_back = 0;
+ stbi__gif g;
+ int stride;
+ memset(&g, 0, sizeof(g));
+ if (delays) {
+ *delays = 0;
+ }
+
+ do {
+ u = stbi__gif_load_next(s, &g, comp, req_comp, two_back);
+ if (u == (stbi_uc *)s)
+ u = 0; // end of animated gif marker
+
+ if (u) {
+ *x = g.w;
+ *y = g.h;
+ ++layers;
+ stride = g.w * g.h * 4;
+
+ if (out) {
+ out = (stbi_uc *)STBI_REALLOC(out, layers * stride);
+ if (delays) {
+ *delays = (int *)STBI_REALLOC(*delays, sizeof(int) * layers);
+ }
+ } else {
+ out = (stbi_uc *)stbi__malloc(layers * stride);
+ if (delays) {
+ *delays = (int *)stbi__malloc(layers * sizeof(int));
+ }
+ }
+ memcpy(out + ((layers - 1) * stride), u, stride);
+ if (layers >= 2) {
+ two_back = out - 2 * stride;
+ }
+
+ if (delays) {
+ (*delays)[layers - 1U] = g.delay;
+ }
+ }
+ } while (u != 0);
+
+ // free temp buffer;
+ STBI_FREE(g.out);
+ STBI_FREE(g.history);
+ STBI_FREE(g.background);
+
+ // do the final conversion after loading everything;
+ if (req_comp && req_comp != 4)
+ out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h);
+
+ *z = layers;
+ return out;
+ } else {
+ return stbi__errpuc("not GIF", "Image was not as a gif type.");
+ }
+}
+
+static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) {
+ stbi_uc *u = 0;
+ stbi__gif g;
+ memset(&g, 0, sizeof(g));
+
+ u = stbi__gif_load_next(s, &g, comp, req_comp, 0);
+ if (u == (stbi_uc *)s)
+ u = 0; // end of animated gif marker
+ if (u) {
+ *x = g.w;
+ *y = g.h;
+
+ // moved conversion to after successful load so that the same
+ // can be done for multiple frames.
+ if (req_comp && req_comp != 4)
+ u = stbi__convert_format(u, 4, req_comp, g.w, g.h);
+ }
+
+ // free buffers needed for multiple frame loading;
+ STBI_FREE(g.history);
+ STBI_FREE(g.background);
+
+ return u;
+}
+
+static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) { return stbi__gif_info_raw(s, x, y, comp); }
#endif
// *************************************************************************************************
// Radiance RGBE HDR loader
// originally by Nicolas Schulz
#ifndef STBI_NO_HDR
-static int stbi__hdr_test_core(stbi__context *s, const char *signature)
-{
- int i;
- for (i=0; signature[i]; ++i)
- if (stbi__get8(s) != signature[i])
- return 0;
- stbi__rewind(s);
- return 1;
-}
-
-static int stbi__hdr_test(stbi__context* s)
-{
- int r = stbi__hdr_test_core(s, "#?RADIANCE\n");
- stbi__rewind(s);
- if(!r) {
- r = stbi__hdr_test_core(s, "#?RGBE\n");
- stbi__rewind(s);
- }
- return r;
-}
-
-#define STBI__HDR_BUFLEN 1024
-static char *stbi__hdr_gettoken(stbi__context *z, char *buffer)
-{
- int len=0;
- char c = '\0';
-
- c = (char) stbi__get8(z);
-
- while (!stbi__at_eof(z) && c != '\n') {
- buffer[len++] = c;
- if (len == STBI__HDR_BUFLEN-1) {
- // flush to end of line
- while (!stbi__at_eof(z) && stbi__get8(z) != '\n')
- ;
- break;
- }
- c = (char) stbi__get8(z);
- }
-
- buffer[len] = 0;
- return buffer;
-}
-
-static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp)
-{
- if ( input[3] != 0 ) {
- float f1;
- // Exponent
- f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8));
- if (req_comp <= 2)
- output[0] = (input[0] + input[1] + input[2]) * f1 / 3;
- else {
- output[0] = input[0] * f1;
- output[1] = input[1] * f1;
- output[2] = input[2] * f1;
- }
- if (req_comp == 2) output[1] = 1;
- if (req_comp == 4) output[3] = 1;
- } else {
- switch (req_comp) {
- case 4: output[3] = 1; /* fallthrough */
- case 3: output[0] = output[1] = output[2] = 0;
- break;
- case 2: output[1] = 1; /* fallthrough */
- case 1: output[0] = 0;
- break;
- }
- }
-}
-
-static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
-{
- char buffer[STBI__HDR_BUFLEN];
- char *token;
- int valid = 0;
- int width, height;
- stbi_uc *scanline;
- float *hdr_data;
- int len;
- unsigned char count, value;
- int i, j, k, c1,c2, z;
- const char *headerToken;
- STBI_NOTUSED(ri);
-
- // Check identifier
- headerToken = stbi__hdr_gettoken(s,buffer);
- if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0)
- return stbi__errpf("not HDR", "Corrupt HDR image");
-
- // Parse header
- for(;;) {
- token = stbi__hdr_gettoken(s,buffer);
- if (token[0] == 0) break;
- if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
- }
-
- if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format");
-
- // Parse width and height
- // can't use sscanf() if we're not using stdio!
- token = stbi__hdr_gettoken(s,buffer);
- if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format");
- token += 3;
- height = (int) strtol(token, &token, 10);
- while (*token == ' ') ++token;
- if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format");
- token += 3;
- width = (int) strtol(token, NULL, 10);
-
- *x = width;
- *y = height;
-
- if (comp) *comp = 3;
- if (req_comp == 0) req_comp = 3;
-
- if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0))
- return stbi__errpf("too large", "HDR image is too large");
-
- // Read data
- hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);
- if (!hdr_data)
- return stbi__errpf("outofmem", "Out of memory");
-
- // Load image data
- // image data is stored as some number of sca
- if ( width < 8 || width >= 32768) {
- // Read flat data
- for (j=0; j < height; ++j) {
- for (i=0; i < width; ++i) {
- stbi_uc rgbe[4];
- main_decode_loop:
- stbi__getn(s, rgbe, 4);
- stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp);
- }
- }
- } else {
- // Read RLE-encoded data
- scanline = NULL;
-
- for (j = 0; j < height; ++j) {
- c1 = stbi__get8(s);
- c2 = stbi__get8(s);
- len = stbi__get8(s);
- if (c1 != 2 || c2 != 2 || (len & 0x80)) {
- // not run-length encoded, so we have to actually use THIS data as a decoded
- // pixel (note this can't be a valid pixel--one of RGB must be >= 128)
- stbi_uc rgbe[4];
- rgbe[0] = (stbi_uc) c1;
- rgbe[1] = (stbi_uc) c2;
- rgbe[2] = (stbi_uc) len;
- rgbe[3] = (stbi_uc) stbi__get8(s);
- stbi__hdr_convert(hdr_data, rgbe, req_comp);
- i = 1;
- j = 0;
- STBI_FREE(scanline);
- goto main_decode_loop; // yes, this makes no sense
- }
- len <<= 8;
- len |= stbi__get8(s);
- if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
- if (scanline == NULL) {
- scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0);
- if (!scanline) {
- STBI_FREE(hdr_data);
- return stbi__errpf("outofmem", "Out of memory");
- }
- }
-
- for (k = 0; k < 4; ++k) {
- int nleft;
- i = 0;
- while ((nleft = width - i) > 0) {
- count = stbi__get8(s);
- if (count > 128) {
- // Run
- value = stbi__get8(s);
- count -= 128;
- if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
- for (z = 0; z < count; ++z)
- scanline[i++ * 4 + k] = value;
- } else {
- // Dump
- if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
- for (z = 0; z < count; ++z)
- scanline[i++ * 4 + k] = stbi__get8(s);
- }
- }
- }
- for (i=0; i < width; ++i)
- stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp);
- }
- if (scanline)
- STBI_FREE(scanline);
- }
-
- return hdr_data;
-}
-
-static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)
-{
- char buffer[STBI__HDR_BUFLEN];
- char *token;
- int valid = 0;
- int dummy;
-
- if (!x) x = &dummy;
- if (!y) y = &dummy;
- if (!comp) comp = &dummy;
-
- if (stbi__hdr_test(s) == 0) {
- stbi__rewind( s );
- return 0;
- }
-
- for(;;) {
- token = stbi__hdr_gettoken(s,buffer);
- if (token[0] == 0) break;
- if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
- }
-
- if (!valid) {
- stbi__rewind( s );
- return 0;
- }
- token = stbi__hdr_gettoken(s,buffer);
- if (strncmp(token, "-Y ", 3)) {
- stbi__rewind( s );
- return 0;
- }
- token += 3;
- *y = (int) strtol(token, &token, 10);
- while (*token == ' ') ++token;
- if (strncmp(token, "+X ", 3)) {
- stbi__rewind( s );
- return 0;
- }
- token += 3;
- *x = (int) strtol(token, NULL, 10);
- *comp = 3;
- return 1;
+static int stbi__hdr_test_core(stbi__context *s, const char *signature) {
+ int i;
+ for (i = 0; signature[i]; ++i)
+ if (stbi__get8(s) != signature[i])
+ return 0;
+ stbi__rewind(s);
+ return 1;
+}
+
+static int stbi__hdr_test(stbi__context *s) {
+ int r = stbi__hdr_test_core(s, "#?RADIANCE\n");
+ stbi__rewind(s);
+ if (!r) {
+ r = stbi__hdr_test_core(s, "#?RGBE\n");
+ stbi__rewind(s);
+ }
+ return r;
+}
+
+#define STBI__HDR_BUFLEN 1024
+static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) {
+ int len = 0;
+ char c = '\0';
+
+ c = (char)stbi__get8(z);
+
+ while (!stbi__at_eof(z) && c != '\n') {
+ buffer[len++] = c;
+ if (len == STBI__HDR_BUFLEN - 1) {
+ // flush to end of line
+ while (!stbi__at_eof(z) && stbi__get8(z) != '\n')
+ ;
+ break;
+ }
+ c = (char)stbi__get8(z);
+ }
+
+ buffer[len] = 0;
+ return buffer;
+}
+
+static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) {
+ if (input[3] != 0) {
+ float f1;
+ // Exponent
+ f1 = (float)ldexp(1.0f, input[3] - (int)(128 + 8));
+ if (req_comp <= 2)
+ output[0] = (input[0] + input[1] + input[2]) * f1 / 3;
+ else {
+ output[0] = input[0] * f1;
+ output[1] = input[1] * f1;
+ output[2] = input[2] * f1;
+ }
+ if (req_comp == 2)
+ output[1] = 1;
+ if (req_comp == 4)
+ output[3] = 1;
+ } else {
+ switch (req_comp) {
+ case 4:
+ output[3] = 1; /* fallthrough */
+ case 3:
+ output[0] = output[1] = output[2] = 0;
+ break;
+ case 2:
+ output[1] = 1; /* fallthrough */
+ case 1:
+ output[0] = 0;
+ break;
+ }
+ }
+}
+
+static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) {
+ char buffer[STBI__HDR_BUFLEN];
+ char *token;
+ int valid = 0;
+ int width, height;
+ stbi_uc *scanline;
+ float *hdr_data;
+ int len;
+ unsigned char count, value;
+ int i, j, k, c1, c2, z;
+ const char *headerToken;
+ STBI_NOTUSED(ri);
+
+ // Check identifier
+ headerToken = stbi__hdr_gettoken(s, buffer);
+ if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0)
+ return stbi__errpf("not HDR", "Corrupt HDR image");
+
+ // Parse header
+ for (;;) {
+ token = stbi__hdr_gettoken(s, buffer);
+ if (token[0] == 0)
+ break;
+ if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0)
+ valid = 1;
+ }
+
+ if (!valid)
+ return stbi__errpf("unsupported format", "Unsupported HDR format");
+
+ // Parse width and height
+ // can't use sscanf() if we're not using stdio!
+ token = stbi__hdr_gettoken(s, buffer);
+ if (strncmp(token, "-Y ", 3))
+ return stbi__errpf("unsupported data layout", "Unsupported HDR format");
+ token += 3;
+ height = (int)strtol(token, &token, 10);
+ while (*token == ' ')
+ ++token;
+ if (strncmp(token, "+X ", 3))
+ return stbi__errpf("unsupported data layout", "Unsupported HDR format");
+ token += 3;
+ width = (int)strtol(token, NULL, 10);
+
+ *x = width;
+ *y = height;
+
+ if (comp)
+ *comp = 3;
+ if (req_comp == 0)
+ req_comp = 3;
+
+ if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0))
+ return stbi__errpf("too large", "HDR image is too large");
+
+ // Read data
+ hdr_data = (float *)stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);
+ if (!hdr_data)
+ return stbi__errpf("outofmem", "Out of memory");
+
+ // Load image data
+ // image data is stored as some number of sca
+ if (width < 8 || width >= 32768) {
+ // Read flat data
+ for (j = 0; j < height; ++j) {
+ for (i = 0; i < width; ++i) {
+ stbi_uc rgbe[4];
+ main_decode_loop:
+ stbi__getn(s, rgbe, 4);
+ stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp);
+ }
+ }
+ } else {
+ // Read RLE-encoded data
+ scanline = NULL;
+
+ for (j = 0; j < height; ++j) {
+ c1 = stbi__get8(s);
+ c2 = stbi__get8(s);
+ len = stbi__get8(s);
+ if (c1 != 2 || c2 != 2 || (len & 0x80)) {
+ // not run-length encoded, so we have to actually use THIS data as a decoded
+ // pixel (note this can't be a valid pixel--one of RGB must be >= 128)
+ stbi_uc rgbe[4];
+ rgbe[0] = (stbi_uc)c1;
+ rgbe[1] = (stbi_uc)c2;
+ rgbe[2] = (stbi_uc)len;
+ rgbe[3] = (stbi_uc)stbi__get8(s);
+ stbi__hdr_convert(hdr_data, rgbe, req_comp);
+ i = 1;
+ j = 0;
+ STBI_FREE(scanline);
+ goto main_decode_loop; // yes, this makes no sense
+ }
+ len <<= 8;
+ len |= stbi__get8(s);
+ if (len != width) {
+ STBI_FREE(hdr_data);
+ STBI_FREE(scanline);
+ return stbi__errpf("invalid decoded scanline length", "corrupt HDR");
+ }
+ if (scanline == NULL) {
+ scanline = (stbi_uc *)stbi__malloc_mad2(width, 4, 0);
+ if (!scanline) {
+ STBI_FREE(hdr_data);
+ return stbi__errpf("outofmem", "Out of memory");
+ }
+ }
+
+ for (k = 0; k < 4; ++k) {
+ int nleft;
+ i = 0;
+ while ((nleft = width - i) > 0) {
+ count = stbi__get8(s);
+ if (count > 128) {
+ // Run
+ value = stbi__get8(s);
+ count -= 128;
+ if (count > nleft) {
+ STBI_FREE(hdr_data);
+ STBI_FREE(scanline);
+ return stbi__errpf("corrupt", "bad RLE data in HDR");
+ }
+ for (z = 0; z < count; ++z)
+ scanline[i++ * 4 + k] = value;
+ } else {
+ // Dump
+ if (count > nleft) {
+ STBI_FREE(hdr_data);
+ STBI_FREE(scanline);
+ return stbi__errpf("corrupt", "bad RLE data in HDR");
+ }
+ for (z = 0; z < count; ++z)
+ scanline[i++ * 4 + k] = stbi__get8(s);
+ }
+ }
+ }
+ for (i = 0; i < width; ++i)
+ stbi__hdr_convert(hdr_data + (j * width + i) * req_comp, scanline + i * 4, req_comp);
+ }
+ if (scanline)
+ STBI_FREE(scanline);
+ }
+
+ return hdr_data;
+}
+
+static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) {
+ char buffer[STBI__HDR_BUFLEN];
+ char *token;
+ int valid = 0;
+ int dummy;
+
+ if (!x)
+ x = &dummy;
+ if (!y)
+ y = &dummy;
+ if (!comp)
+ comp = &dummy;
+
+ if (stbi__hdr_test(s) == 0) {
+ stbi__rewind(s);
+ return 0;
+ }
+
+ for (;;) {
+ token = stbi__hdr_gettoken(s, buffer);
+ if (token[0] == 0)
+ break;
+ if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0)
+ valid = 1;
+ }
+
+ if (!valid) {
+ stbi__rewind(s);
+ return 0;
+ }
+ token = stbi__hdr_gettoken(s, buffer);
+ if (strncmp(token, "-Y ", 3)) {
+ stbi__rewind(s);
+ return 0;
+ }
+ token += 3;
+ *y = (int)strtol(token, &token, 10);
+ while (*token == ' ')
+ ++token;
+ if (strncmp(token, "+X ", 3)) {
+ stbi__rewind(s);
+ return 0;
+ }
+ token += 3;
+ *x = (int)strtol(token, NULL, 10);
+ *comp = 3;
+ return 1;
}
#endif // STBI_NO_HDR
#ifndef STBI_NO_BMP
-static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
-{
- void *p;
- stbi__bmp_data info;
-
- info.all_a = 255;
- p = stbi__bmp_parse_header(s, &info);
- stbi__rewind( s );
- if (p == NULL)
- return 0;
- if (x) *x = s->img_x;
- if (y) *y = s->img_y;
- if (comp) *comp = info.ma ? 4 : 3;
- return 1;
+static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) {
+ void *p;
+ stbi__bmp_data info;
+
+ info.all_a = 255;
+ p = stbi__bmp_parse_header(s, &info);
+ stbi__rewind(s);
+ if (p == NULL)
+ return 0;
+ if (x)
+ *x = s->img_x;
+ if (y)
+ *y = s->img_y;
+ if (comp)
+ *comp = info.ma ? 4 : 3;
+ return 1;
}
#endif
#ifndef STBI_NO_PSD
-static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp)
-{
- int channelCount, dummy, depth;
- if (!x) x = &dummy;
- if (!y) y = &dummy;
- if (!comp) comp = &dummy;
- if (stbi__get32be(s) != 0x38425053) {
- stbi__rewind( s );
- return 0;
- }
- if (stbi__get16be(s) != 1) {
- stbi__rewind( s );
- return 0;
- }
- stbi__skip(s, 6);
- channelCount = stbi__get16be(s);
- if (channelCount < 0 || channelCount > 16) {
- stbi__rewind( s );
- return 0;
- }
- *y = stbi__get32be(s);
- *x = stbi__get32be(s);
- depth = stbi__get16be(s);
- if (depth != 8 && depth != 16) {
- stbi__rewind( s );
- return 0;
- }
- if (stbi__get16be(s) != 3) {
- stbi__rewind( s );
- return 0;
- }
- *comp = 4;
- return 1;
-}
-
-static int stbi__psd_is16(stbi__context *s)
-{
- int channelCount, depth;
- if (stbi__get32be(s) != 0x38425053) {
- stbi__rewind( s );
- return 0;
- }
- if (stbi__get16be(s) != 1) {
- stbi__rewind( s );
- return 0;
- }
- stbi__skip(s, 6);
- channelCount = stbi__get16be(s);
- if (channelCount < 0 || channelCount > 16) {
- stbi__rewind( s );
- return 0;
- }
- (void) stbi__get32be(s);
- (void) stbi__get32be(s);
- depth = stbi__get16be(s);
- if (depth != 16) {
- stbi__rewind( s );
- return 0;
- }
- return 1;
+static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) {
+ int channelCount, dummy, depth;
+ if (!x)
+ x = &dummy;
+ if (!y)
+ y = &dummy;
+ if (!comp)
+ comp = &dummy;
+ if (stbi__get32be(s) != 0x38425053) {
+ stbi__rewind(s);
+ return 0;
+ }
+ if (stbi__get16be(s) != 1) {
+ stbi__rewind(s);
+ return 0;
+ }
+ stbi__skip(s, 6);
+ channelCount = stbi__get16be(s);
+ if (channelCount < 0 || channelCount > 16) {
+ stbi__rewind(s);
+ return 0;
+ }
+ *y = stbi__get32be(s);
+ *x = stbi__get32be(s);
+ depth = stbi__get16be(s);
+ if (depth != 8 && depth != 16) {
+ stbi__rewind(s);
+ return 0;
+ }
+ if (stbi__get16be(s) != 3) {
+ stbi__rewind(s);
+ return 0;
+ }
+ *comp = 4;
+ return 1;
+}
+
+static int stbi__psd_is16(stbi__context *s) {
+ int channelCount, depth;
+ if (stbi__get32be(s) != 0x38425053) {
+ stbi__rewind(s);
+ return 0;
+ }
+ if (stbi__get16be(s) != 1) {
+ stbi__rewind(s);
+ return 0;
+ }
+ stbi__skip(s, 6);
+ channelCount = stbi__get16be(s);
+ if (channelCount < 0 || channelCount > 16) {
+ stbi__rewind(s);
+ return 0;
+ }
+ (void)stbi__get32be(s);
+ (void)stbi__get32be(s);
+ depth = stbi__get16be(s);
+ if (depth != 16) {
+ stbi__rewind(s);
+ return 0;
+ }
+ return 1;
}
#endif
#ifndef STBI_NO_PIC
-static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp)
-{
- int act_comp=0,num_packets=0,chained,dummy;
- stbi__pic_packet packets[10];
-
- if (!x) x = &dummy;
- if (!y) y = &dummy;
- if (!comp) comp = &dummy;
-
- if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) {
- stbi__rewind(s);
- return 0;
- }
-
- stbi__skip(s, 88);
-
- *x = stbi__get16be(s);
- *y = stbi__get16be(s);
- if (stbi__at_eof(s)) {
- stbi__rewind( s);
- return 0;
- }
- if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) {
- stbi__rewind( s );
- return 0;
- }
-
- stbi__skip(s, 8);
-
- do {
- stbi__pic_packet *packet;
-
- if (num_packets==sizeof(packets)/sizeof(packets[0]))
- return 0;
-
- packet = &packets[num_packets++];
- chained = stbi__get8(s);
- packet->size = stbi__get8(s);
- packet->type = stbi__get8(s);
- packet->channel = stbi__get8(s);
- act_comp |= packet->channel;
-
- if (stbi__at_eof(s)) {
- stbi__rewind( s );
- return 0;
- }
- if (packet->size != 8) {
- stbi__rewind( s );
- return 0;
- }
- } while (chained);
-
- *comp = (act_comp & 0x10 ? 4 : 3);
-
- return 1;
+static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) {
+ int act_comp = 0, num_packets = 0, chained, dummy;
+ stbi__pic_packet packets[10];
+
+ if (!x)
+ x = &dummy;
+ if (!y)
+ y = &dummy;
+ if (!comp)
+ comp = &dummy;
+
+ if (!stbi__pic_is4(s, "\x53\x80\xF6\x34")) {
+ stbi__rewind(s);
+ return 0;
+ }
+
+ stbi__skip(s, 88);
+
+ *x = stbi__get16be(s);
+ *y = stbi__get16be(s);
+ if (stbi__at_eof(s)) {
+ stbi__rewind(s);
+ return 0;
+ }
+ if ((*x) != 0 && (1 << 28) / (*x) < (*y)) {
+ stbi__rewind(s);
+ return 0;
+ }
+
+ stbi__skip(s, 8);
+
+ do {
+ stbi__pic_packet *packet;
+
+ if (num_packets == sizeof(packets) / sizeof(packets[0]))
+ return 0;
+
+ packet = &packets[num_packets++];
+ chained = stbi__get8(s);
+ packet->size = stbi__get8(s);
+ packet->type = stbi__get8(s);
+ packet->channel = stbi__get8(s);
+ act_comp |= packet->channel;
+
+ if (stbi__at_eof(s)) {
+ stbi__rewind(s);
+ return 0;
+ }
+ if (packet->size != 8) {
+ stbi__rewind(s);
+ return 0;
+ }
+ } while (chained);
+
+ *comp = (act_comp & 0x10 ? 4 : 3);
+
+ return 1;
}
#endif
#ifndef STBI_NO_PNM
-static int stbi__pnm_test(stbi__context *s)
-{
- char p, t;
- p = (char) stbi__get8(s);
- t = (char) stbi__get8(s);
- if (p != 'P' || (t != '5' && t != '6')) {
- stbi__rewind( s );
- return 0;
- }
- return 1;
+static int stbi__pnm_test(stbi__context *s) {
+ char p, t;
+ p = (char)stbi__get8(s);
+ t = (char)stbi__get8(s);
+ if (p != 'P' || (t != '5' && t != '6')) {
+ stbi__rewind(s);
+ return 0;
+ }
+ return 1;
}
-static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
-{
- stbi_uc *out;
- STBI_NOTUSED(ri);
+static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) {
+ stbi_uc *out;
+ STBI_NOTUSED(ri);
- if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
- return 0;
+ if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
+ return 0;
- *x = s->img_x;
- *y = s->img_y;
- if (comp) *comp = s->img_n;
+ *x = s->img_x;
+ *y = s->img_y;
+ if (comp)
+ *comp = s->img_n;
- if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0))
- return stbi__errpuc("too large", "PNM too large");
+ if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0))
+ return stbi__errpuc("too large", "PNM too large");
- out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0);
- if (!out) return stbi__errpuc("outofmem", "Out of memory");
- stbi__getn(s, out, s->img_n * s->img_x * s->img_y);
+ out = (stbi_uc *)stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0);
+ if (!out)
+ return stbi__errpuc("outofmem", "Out of memory");
+ stbi__getn(s, out, s->img_n * s->img_x * s->img_y);
- if (req_comp && req_comp != s->img_n) {
- out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
- if (out == NULL) return out; // stbi__convert_format frees input on failure
- }
- return out;
+ if (req_comp && req_comp != s->img_n) {
+ out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
+ if (out == NULL)
+ return out; // stbi__convert_format frees input on failure
+ }
+ return out;
}
-static int stbi__pnm_isspace(char c)
-{
- return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
+static int stbi__pnm_isspace(char c) {
+ return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
}
-static void stbi__pnm_skip_whitespace(stbi__context *s, char *c)
-{
- for (;;) {
- while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
- *c = (char) stbi__get8(s);
+static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) {
+ for (;;) {
+ while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
+ *c = (char)stbi__get8(s);
- if (stbi__at_eof(s) || *c != '#')
- break;
+ if (stbi__at_eof(s) || *c != '#')
+ break;
- while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' )
- *c = (char) stbi__get8(s);
- }
+ while (!stbi__at_eof(s) && *c != '\n' && *c != '\r')
+ *c = (char)stbi__get8(s);
+ }
}
-static int stbi__pnm_isdigit(char c)
-{
- return c >= '0' && c <= '9';
-}
+static int stbi__pnm_isdigit(char c) { return c >= '0' && c <= '9'; }
-static int stbi__pnm_getinteger(stbi__context *s, char *c)
-{
- int value = 0;
+static int stbi__pnm_getinteger(stbi__context *s, char *c) {
+ int value = 0;
- while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
- value = value*10 + (*c - '0');
- *c = (char) stbi__get8(s);
- }
+ while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
+ value = value * 10 + (*c - '0');
+ *c = (char)stbi__get8(s);
+ }
- return value;
+ return value;
}
-static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp)
-{
- int maxv, dummy;
- char c, p, t;
+static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) {
+ int maxv, dummy;
+ char c, p, t;
- if (!x) x = &dummy;
- if (!y) y = &dummy;
- if (!comp) comp = &dummy;
+ if (!x)
+ x = &dummy;
+ if (!y)
+ y = &dummy;
+ if (!comp)
+ comp = &dummy;
- stbi__rewind(s);
+ stbi__rewind(s);
- // Get identifier
- p = (char) stbi__get8(s);
- t = (char) stbi__get8(s);
- if (p != 'P' || (t != '5' && t != '6')) {
- stbi__rewind(s);
- return 0;
- }
+ // Get identifier
+ p = (char)stbi__get8(s);
+ t = (char)stbi__get8(s);
+ if (p != 'P' || (t != '5' && t != '6')) {
+ stbi__rewind(s);
+ return 0;
+ }
- *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm
+ *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm
- c = (char) stbi__get8(s);
- stbi__pnm_skip_whitespace(s, &c);
+ c = (char)stbi__get8(s);
+ stbi__pnm_skip_whitespace(s, &c);
- *x = stbi__pnm_getinteger(s, &c); // read width
- stbi__pnm_skip_whitespace(s, &c);
+ *x = stbi__pnm_getinteger(s, &c); // read width
+ stbi__pnm_skip_whitespace(s, &c);
- *y = stbi__pnm_getinteger(s, &c); // read height
- stbi__pnm_skip_whitespace(s, &c);
+ *y = stbi__pnm_getinteger(s, &c); // read height
+ stbi__pnm_skip_whitespace(s, &c);
- maxv = stbi__pnm_getinteger(s, &c); // read max value
+ maxv = stbi__pnm_getinteger(s, &c); // read max value
- if (maxv > 255)
- return stbi__err("max value > 255", "PPM image not 8-bit");
- else
- return 1;
+ if (maxv > 255)
+ return stbi__err("max value > 255", "PPM image not 8-bit");
+ else
+ return 1;
}
#endif
-static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp)
-{
- #ifndef STBI_NO_JPEG
- if (stbi__jpeg_info(s, x, y, comp)) return 1;
- #endif
+static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) {
+#ifndef STBI_NO_JPEG
+ if (stbi__jpeg_info(s, x, y, comp))
+ return 1;
+#endif
- #ifndef STBI_NO_PNG
- if (stbi__png_info(s, x, y, comp)) return 1;
- #endif
+#ifndef STBI_NO_PNG
+ if (stbi__png_info(s, x, y, comp))
+ return 1;
+#endif
- #ifndef STBI_NO_GIF
- if (stbi__gif_info(s, x, y, comp)) return 1;
- #endif
+#ifndef STBI_NO_GIF
+ if (stbi__gif_info(s, x, y, comp))
+ return 1;
+#endif
- #ifndef STBI_NO_BMP
- if (stbi__bmp_info(s, x, y, comp)) return 1;
- #endif
+#ifndef STBI_NO_BMP
+ if (stbi__bmp_info(s, x, y, comp))
+ return 1;
+#endif
- #ifndef STBI_NO_PSD
- if (stbi__psd_info(s, x, y, comp)) return 1;
- #endif
+#ifndef STBI_NO_PSD
+ if (stbi__psd_info(s, x, y, comp))
+ return 1;
+#endif
- #ifndef STBI_NO_PIC
- if (stbi__pic_info(s, x, y, comp)) return 1;
- #endif
+#ifndef STBI_NO_PIC
+ if (stbi__pic_info(s, x, y, comp))
+ return 1;
+#endif
- #ifndef STBI_NO_PNM
- if (stbi__pnm_info(s, x, y, comp)) return 1;
- #endif
+#ifndef STBI_NO_PNM
+ if (stbi__pnm_info(s, x, y, comp))
+ return 1;
+#endif
- #ifndef STBI_NO_HDR
- if (stbi__hdr_info(s, x, y, comp)) return 1;
- #endif
+#ifndef STBI_NO_HDR
+ if (stbi__hdr_info(s, x, y, comp))
+ return 1;
+#endif
- // test tga last because it's a crappy test!
- #ifndef STBI_NO_TGA
- if (stbi__tga_info(s, x, y, comp))
- return 1;
- #endif
- return stbi__err("unknown image type", "Image not of any known type, or corrupt");
+// test tga last because it's a crappy test!
+#ifndef STBI_NO_TGA
+ if (stbi__tga_info(s, x, y, comp))
+ return 1;
+#endif
+ return stbi__err("unknown image type", "Image not of any known type, or corrupt");
}
-static int stbi__is_16_main(stbi__context *s)
-{
- #ifndef STBI_NO_PNG
- if (stbi__png_is16(s)) return 1;
- #endif
+static int stbi__is_16_main(stbi__context *s) {
+#ifndef STBI_NO_PNG
+ if (stbi__png_is16(s))
+ return 1;
+#endif
- #ifndef STBI_NO_PSD
- if (stbi__psd_is16(s)) return 1;
- #endif
+#ifndef STBI_NO_PSD
+ if (stbi__psd_is16(s))
+ return 1;
+#endif
- return 0;
+ return 0;
}
#ifndef STBI_NO_STDIO
-STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp)
-{
- FILE *f = stbi__fopen(filename, "rb");
- int result;
- if (!f) return stbi__err("can't fopen", "Unable to open file");
- result = stbi_info_from_file(f, x, y, comp);
- fclose(f);
- return result;
-}
-
-STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp)
-{
- int r;
- stbi__context s;
- long pos = ftell(f);
- stbi__start_file(&s, f);
- r = stbi__info_main(&s,x,y,comp);
- fseek(f,pos,SEEK_SET);
- return r;
-}
-
-STBIDEF int stbi_is_16_bit(char const *filename)
-{
- FILE *f = stbi__fopen(filename, "rb");
- int result;
- if (!f) return stbi__err("can't fopen", "Unable to open file");
- result = stbi_is_16_bit_from_file(f);
- fclose(f);
- return result;
-}
-
-STBIDEF int stbi_is_16_bit_from_file(FILE *f)
-{
- int r;
- stbi__context s;
- long pos = ftell(f);
- stbi__start_file(&s, f);
- r = stbi__is_16_main(&s);
- fseek(f,pos,SEEK_SET);
- return r;
+STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) {
+ FILE *f = stbi__fopen(filename, "rb");
+ int result;
+ if (!f)
+ return stbi__err("can't fopen", "Unable to open file");
+ result = stbi_info_from_file(f, x, y, comp);
+ fclose(f);
+ return result;
+}
+
+STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) {
+ int r;
+ stbi__context s;
+ long pos = ftell(f);
+ stbi__start_file(&s, f);
+ r = stbi__info_main(&s, x, y, comp);
+ fseek(f, pos, SEEK_SET);
+ return r;
+}
+
+STBIDEF int stbi_is_16_bit(char const *filename) {
+ FILE *f = stbi__fopen(filename, "rb");
+ int result;
+ if (!f)
+ return stbi__err("can't fopen", "Unable to open file");
+ result = stbi_is_16_bit_from_file(f);
+ fclose(f);
+ return result;
+}
+
+STBIDEF int stbi_is_16_bit_from_file(FILE *f) {
+ int r;
+ stbi__context s;
+ long pos = ftell(f);
+ stbi__start_file(&s, f);
+ r = stbi__is_16_main(&s);
+ fseek(f, pos, SEEK_SET);
+ return r;
}
#endif // !STBI_NO_STDIO
-STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp)
-{
- stbi__context s;
- stbi__start_mem(&s,buffer,len);
- return stbi__info_main(&s,x,y,comp);
+STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) {
+ stbi__context s;
+ stbi__start_mem(&s, buffer, len);
+ return stbi__info_main(&s, x, y, comp);
}
-STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp)
-{
- stbi__context s;
- stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
- return stbi__info_main(&s,x,y,comp);
+STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) {
+ stbi__context s;
+ stbi__start_callbacks(&s, (stbi_io_callbacks *)c, user);
+ return stbi__info_main(&s, x, y, comp);
}
-STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len)
-{
- stbi__context s;
- stbi__start_mem(&s,buffer,len);
- return stbi__is_16_main(&s);
+STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) {
+ stbi__context s;
+ stbi__start_mem(&s, buffer, len);
+ return stbi__is_16_main(&s);
}
-STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user)
-{
- stbi__context s;
- stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
- return stbi__is_16_main(&s);
+STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) {
+ stbi__context s;
+ stbi__start_callbacks(&s, (stbi_io_callbacks *)c, user);
+ return stbi__is_16_main(&s);
}
#endif // STB_IMAGE_IMPLEMENTATION
/*
revision history:
- 2.19 (2018-02-11) fix warning
- 2.18 (2018-01-30) fix warnings
- 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug
- 1-bit BMP
- *_is_16_bit api
- avoid warnings
- 2.16 (2017-07-23) all functions have 16-bit variants;
- STBI_NO_STDIO works again;
- compilation fixes;
- fix rounding in unpremultiply;
- optimize vertical flip;
- disable raw_len validation;
- documentation fixes
- 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode;
- warning fixes; disable run-time SSE detection on gcc;
- uniform handling of optional "return" values;
- thread-safe initialization of zlib tables
- 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
- 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now
- 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
- 2.11 (2016-04-02) allocate large structures on the stack
- remove white matting for transparent PSD
- fix reported channel count for PNG & BMP
- re-enable SSE2 in non-gcc 64-bit
- support RGB-formatted JPEG
- read 16-bit PNGs (only as 8-bit)
- 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED
- 2.09 (2016-01-16) allow comments in PNM files
- 16-bit-per-pixel TGA (not bit-per-component)
- info() for TGA could break due to .hdr handling
- info() for BMP to shares code instead of sloppy parse
- can use STBI_REALLOC_SIZED if allocator doesn't support realloc
- code cleanup
- 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
- 2.07 (2015-09-13) fix compiler warnings
- partial animated GIF support
- limited 16-bpc PSD support
- #ifdef unused functions
- bug with < 92 byte PIC,PNM,HDR,TGA
- 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
- 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning
- 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit
- 2.03 (2015-04-12) extra corruption checking (mmozeiko)
- stbi_set_flip_vertically_on_load (nguillemot)
- fix NEON support; fix mingw support
- 2.02 (2015-01-19) fix incorrect assert, fix warning
- 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2
- 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
- 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg)
- progressive JPEG (stb)
- PGM/PPM support (Ken Miller)
- STBI_MALLOC,STBI_REALLOC,STBI_FREE
- GIF bugfix -- seemingly never worked
- STBI_NO_*, STBI_ONLY_*
- 1.48 (2014-12-14) fix incorrectly-named assert()
- 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb)
- optimize PNG (ryg)
- fix bug in interlaced PNG with user-specified channel count (stb)
- 1.46 (2014-08-26)
- fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG
- 1.45 (2014-08-16)
- fix MSVC-ARM internal compiler error by wrapping malloc
- 1.44 (2014-08-07)
- various warning fixes from Ronny Chevalier
- 1.43 (2014-07-15)
- fix MSVC-only compiler problem in code changed in 1.42
- 1.42 (2014-07-09)
- don't define _CRT_SECURE_NO_WARNINGS (affects user code)
- fixes to stbi__cleanup_jpeg path
- added STBI_ASSERT to avoid requiring assert.h
- 1.41 (2014-06-25)
- fix search&replace from 1.36 that messed up comments/error messages
- 1.40 (2014-06-22)
- fix gcc struct-initialization warning
- 1.39 (2014-06-15)
- fix to TGA optimization when req_comp != number of components in TGA;
- fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite)
- add support for BMP version 5 (more ignored fields)
- 1.38 (2014-06-06)
- suppress MSVC warnings on integer casts truncating values
- fix accidental rename of 'skip' field of I/O
- 1.37 (2014-06-04)
- remove duplicate typedef
- 1.36 (2014-06-03)
- convert to header file single-file library
- if de-iphone isn't set, load iphone images color-swapped instead of returning NULL
- 1.35 (2014-05-27)
- various warnings
- fix broken STBI_SIMD path
- fix bug where stbi_load_from_file no longer left file pointer in correct place
- fix broken non-easy path for 32-bit BMP (possibly never used)
- TGA optimization by Arseny Kapoulkine
- 1.34 (unknown)
- use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case
- 1.33 (2011-07-14)
- make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements
- 1.32 (2011-07-13)
- support for "info" function for all supported filetypes (SpartanJ)
- 1.31 (2011-06-20)
- a few more leak fixes, bug in PNG handling (SpartanJ)
- 1.30 (2011-06-11)
- added ability to load files via callbacks to accomidate custom input streams (Ben Wenger)
- removed deprecated format-specific test/load functions
- removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway
- error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha)
- fix inefficiency in decoding 32-bit BMP (David Woo)
- 1.29 (2010-08-16)
- various warning fixes from Aurelien Pocheville
- 1.28 (2010-08-01)
- fix bug in GIF palette transparency (SpartanJ)
- 1.27 (2010-08-01)
- cast-to-stbi_uc to fix warnings
- 1.26 (2010-07-24)
- fix bug in file buffering for PNG reported by SpartanJ
- 1.25 (2010-07-17)
- refix trans_data warning (Won Chun)
- 1.24 (2010-07-12)
- perf improvements reading from files on platforms with lock-heavy fgetc()
- minor perf improvements for jpeg
- deprecated type-specific functions so we'll get feedback if they're needed
- attempt to fix trans_data warning (Won Chun)
- 1.23 fixed bug in iPhone support
- 1.22 (2010-07-10)
- removed image *writing* support
- stbi_info support from Jetro Lauha
- GIF support from Jean-Marc Lienher
- iPhone PNG-extensions from James Brown
- warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva)
- 1.21 fix use of 'stbi_uc' in header (reported by jon blow)
- 1.20 added support for Softimage PIC, by Tom Seddon
- 1.19 bug in interlaced PNG corruption check (found by ryg)
- 1.18 (2008-08-02)
- fix a threading bug (local mutable static)
- 1.17 support interlaced PNG
- 1.16 major bugfix - stbi__convert_format converted one too many pixels
- 1.15 initialize some fields for thread safety
- 1.14 fix threadsafe conversion bug
- header-file-only version (#define STBI_HEADER_FILE_ONLY before including)
- 1.13 threadsafe
- 1.12 const qualifiers in the API
- 1.11 Support installable IDCT, colorspace conversion routines
- 1.10 Fixes for 64-bit (don't use "unsigned long")
- optimized upsampling by Fabian "ryg" Giesen
- 1.09 Fix format-conversion for PSD code (bad global variables!)
- 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz
- 1.07 attempt to fix C++ warning/errors again
- 1.06 attempt to fix C++ warning/errors again
- 1.05 fix TGA loading to return correct *comp and use good luminance calc
- 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free
- 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR
- 1.02 support for (subset of) HDR files, float interface for preferred access to them
- 1.01 fix bug: possible bug in handling right-side up bmps... not sure
- fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all
- 1.00 interface to zlib that skips zlib header
- 0.99 correct handling of alpha in palette
- 0.98 TGA loader by lonesock; dynamically add loaders (untested)
- 0.97 jpeg errors on too large a file; also catch another malloc failure
- 0.96 fix detection of invalid v value - particleman@mollyrocket forum
- 0.95 during header scan, seek to markers in case of padding
- 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same
- 0.93 handle jpegtran output; verbose errors
- 0.92 read 4,8,16,24,32-bit BMP files of several formats
- 0.91 output 24-bit Windows 3.0 BMP files
- 0.90 fix a few more warnings; bump version number to approach 1.0
- 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd
- 0.60 fix compiling as c++
- 0.59 fix warnings: merge Dave Moore's -Wall fixes
- 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian
- 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available
- 0.56 fix bug: zlib uncompressed mode len vs. nlen
- 0.55 fix bug: restart_interval not initialized to 0
- 0.54 allow NULL for 'int *comp'
- 0.53 fix bug in png 3->4; speedup png decoding
- 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments
- 0.51 obey req_comp requests, 1-component jpegs return as 1-component,
- on 'test' only check type, not whether we support this variant
- 0.50 (2006-11-19)
- first released version
+ 2.19 (2018-02-11) fix warning
+ 2.18 (2018-01-30) fix warnings
+ 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug
+ 1-bit BMP
+ *_is_16_bit api
+ avoid warnings
+ 2.16 (2017-07-23) all functions have 16-bit variants;
+ STBI_NO_STDIO works again;
+ compilation fixes;
+ fix rounding in unpremultiply;
+ optimize vertical flip;
+ disable raw_len validation;
+ documentation fixes
+ 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode;
+ warning fixes; disable run-time SSE detection on gcc;
+ uniform handling of optional "return" values;
+ thread-safe initialization of zlib tables
+ 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
+ 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now
+ 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+ 2.11 (2016-04-02) allocate large structures on the stack
+ remove white matting for transparent PSD
+ fix reported channel count for PNG & BMP
+ re-enable SSE2 in non-gcc 64-bit
+ support RGB-formatted JPEG
+ read 16-bit PNGs (only as 8-bit)
+ 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED
+ 2.09 (2016-01-16) allow comments in PNM files
+ 16-bit-per-pixel TGA (not bit-per-component)
+ info() for TGA could break due to .hdr handling
+ info() for BMP to shares code instead of sloppy parse
+ can use STBI_REALLOC_SIZED if allocator doesn't support realloc
+ code cleanup
+ 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
+ 2.07 (2015-09-13) fix compiler warnings
+ partial animated GIF support
+ limited 16-bpc PSD support
+ #ifdef unused functions
+ bug with < 92 byte PIC,PNM,HDR,TGA
+ 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
+ 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning
+ 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit
+ 2.03 (2015-04-12) extra corruption checking (mmozeiko)
+ stbi_set_flip_vertically_on_load (nguillemot)
+ fix NEON support; fix mingw support
+ 2.02 (2015-01-19) fix incorrect assert, fix warning
+ 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2
+ 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
+ 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg)
+ progressive JPEG (stb)
+ PGM/PPM support (Ken Miller)
+ STBI_MALLOC,STBI_REALLOC,STBI_FREE
+ GIF bugfix -- seemingly never worked
+ STBI_NO_*, STBI_ONLY_*
+ 1.48 (2014-12-14) fix incorrectly-named assert()
+ 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb)
+ optimize PNG (ryg)
+ fix bug in interlaced PNG with user-specified channel count (stb)
+ 1.46 (2014-08-26)
+ fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG
+ 1.45 (2014-08-16)
+ fix MSVC-ARM internal compiler error by wrapping malloc
+ 1.44 (2014-08-07)
+ various warning fixes from Ronny Chevalier
+ 1.43 (2014-07-15)
+ fix MSVC-only compiler problem in code changed in 1.42
+ 1.42 (2014-07-09)
+ don't define _CRT_SECURE_NO_WARNINGS (affects user code)
+ fixes to stbi__cleanup_jpeg path
+ added STBI_ASSERT to avoid requiring assert.h
+ 1.41 (2014-06-25)
+ fix search&replace from 1.36 that messed up comments/error messages
+ 1.40 (2014-06-22)
+ fix gcc struct-initialization warning
+ 1.39 (2014-06-15)
+ fix to TGA optimization when req_comp != number of components in TGA;
+ fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite)
+ add support for BMP version 5 (more ignored fields)
+ 1.38 (2014-06-06)
+ suppress MSVC warnings on integer casts truncating values
+ fix accidental rename of 'skip' field of I/O
+ 1.37 (2014-06-04)
+ remove duplicate typedef
+ 1.36 (2014-06-03)
+ convert to header file single-file library
+ if de-iphone isn't set, load iphone images color-swapped instead of returning NULL
+ 1.35 (2014-05-27)
+ various warnings
+ fix broken STBI_SIMD path
+ fix bug where stbi_load_from_file no longer left file pointer in correct place
+ fix broken non-easy path for 32-bit BMP (possibly never used)
+ TGA optimization by Arseny Kapoulkine
+ 1.34 (unknown)
+ use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case
+ 1.33 (2011-07-14)
+ make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements
+ 1.32 (2011-07-13)
+ support for "info" function for all supported filetypes (SpartanJ)
+ 1.31 (2011-06-20)
+ a few more leak fixes, bug in PNG handling (SpartanJ)
+ 1.30 (2011-06-11)
+ added ability to load files via callbacks to accomidate custom input streams (Ben Wenger)
+ removed deprecated format-specific test/load functions
+ removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks
+ anyway error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) fix inefficiency in
+ decoding 32-bit BMP (David Woo) 1.29 (2010-08-16) various warning fixes from Aurelien Pocheville 1.28 (2010-08-01)
+ fix bug in GIF palette transparency (SpartanJ)
+ 1.27 (2010-08-01)
+ cast-to-stbi_uc to fix warnings
+ 1.26 (2010-07-24)
+ fix bug in file buffering for PNG reported by SpartanJ
+ 1.25 (2010-07-17)
+ refix trans_data warning (Won Chun)
+ 1.24 (2010-07-12)
+ perf improvements reading from files on platforms with lock-heavy fgetc()
+ minor perf improvements for jpeg
+ deprecated type-specific functions so we'll get feedback if they're needed
+ attempt to fix trans_data warning (Won Chun)
+ 1.23 fixed bug in iPhone support
+ 1.22 (2010-07-10)
+ removed image *writing* support
+ stbi_info support from Jetro Lauha
+ GIF support from Jean-Marc Lienher
+ iPhone PNG-extensions from James Brown
+ warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva)
+ 1.21 fix use of 'stbi_uc' in header (reported by jon blow)
+ 1.20 added support for Softimage PIC, by Tom Seddon
+ 1.19 bug in interlaced PNG corruption check (found by ryg)
+ 1.18 (2008-08-02)
+ fix a threading bug (local mutable static)
+ 1.17 support interlaced PNG
+ 1.16 major bugfix - stbi__convert_format converted one too many pixels
+ 1.15 initialize some fields for thread safety
+ 1.14 fix threadsafe conversion bug
+ header-file-only version (#define STBI_HEADER_FILE_ONLY before including)
+ 1.13 threadsafe
+ 1.12 const qualifiers in the API
+ 1.11 Support installable IDCT, colorspace conversion routines
+ 1.10 Fixes for 64-bit (don't use "unsigned long")
+ optimized upsampling by Fabian "ryg" Giesen
+ 1.09 Fix format-conversion for PSD code (bad global variables!)
+ 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz
+ 1.07 attempt to fix C++ warning/errors again
+ 1.06 attempt to fix C++ warning/errors again
+ 1.05 fix TGA loading to return correct *comp and use good luminance calc
+ 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free
+ 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR
+ 1.02 support for (subset of) HDR files, float interface for preferred access to them
+ 1.01 fix bug: possible bug in handling right-side up bmps... not sure
+ fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all
+ 1.00 interface to zlib that skips zlib header
+ 0.99 correct handling of alpha in palette
+ 0.98 TGA loader by lonesock; dynamically add loaders (untested)
+ 0.97 jpeg errors on too large a file; also catch another malloc failure
+ 0.96 fix detection of invalid v value - particleman@mollyrocket forum
+ 0.95 during header scan, seek to markers in case of padding
+ 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same
+ 0.93 handle jpegtran output; verbose errors
+ 0.92 read 4,8,16,24,32-bit BMP files of several formats
+ 0.91 output 24-bit Windows 3.0 BMP files
+ 0.90 fix a few more warnings; bump version number to approach 1.0
+ 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd
+ 0.60 fix compiling as c++
+ 0.59 fix warnings: merge Dave Moore's -Wall fixes
+ 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian
+ 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available
+ 0.56 fix bug: zlib uncompressed mode len vs. nlen
+ 0.55 fix bug: restart_interval not initialized to 0
+ 0.54 allow NULL for 'int *comp'
+ 0.53 fix bug in png 3->4; speedup png decoding
+ 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments
+ 0.51 obey req_comp requests, 1-component jpegs return as 1-component,
+ on 'test' only check type, not whether we support this variant
+ 0.50 (2006-11-19)
+ first released version
*/
-
/*
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
There are also five equivalent functions that use an arbitrary write function. You are
expected to open/close your file-equivalent before and after calling these:
- int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes);
- int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
- int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
- int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
- int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
+ int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int
+stride_in_bytes); int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void
+*data); int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); int
+stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); int
+stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
where the callback is:
void stbi_write_func(void *context, void *data, int size);
TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
data, set the global variable 'stbi_write_tga_with_rle' to 0.
-
+
JPEG does ignore alpha channels in input data; quality is between 1 and 100.
Higher quality looks better but results in a bigger image.
JPEG baseline (no JPEG progressive).
CREDITS:
- Sean Barrett - PNG/BMP/TGA
+ Sean Barrett - PNG/BMP/TGA
Baldur Karlsson - HDR
Jean-Sebastien Guay - TGA monochrome
Tim Kelsey - misc enhancements
// if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline'
#ifndef STBIWDEF
#ifdef STB_IMAGE_WRITE_STATIC
-#define STBIWDEF static
+#define STBIWDEF static
#else
#ifdef __cplusplus
-#define STBIWDEF extern "C"
+#define STBIWDEF extern "C"
#else
-#define STBIWDEF extern
+#define STBIWDEF extern
#endif
#endif
#endif
-#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations
+#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations
extern int stbi_write_tga_with_rle;
extern int stbi_write_png_compression_level;
extern int stbi_write_force_png_filter;
#endif
#ifndef STBI_WRITE_NO_STDIO
-STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
-STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
-STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
+STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
+STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
+STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
-STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
+STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
#ifdef STBI_WINDOWS_UTF8
-STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
+STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t *input);
#endif
#endif
typedef void stbi_write_func(void *context, void *data, int size);
-STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes);
-STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
-STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
+STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data,
+ int stride_in_bytes);
+STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
+STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
-STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
+STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data,
+ int quality);
STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean);
-#endif//INCLUDE_STB_IMAGE_WRITE_H
+#endif // INCLUDE_STB_IMAGE_WRITE_H
#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
#ifdef _WIN32
- #ifndef _CRT_SECURE_NO_WARNINGS
- #define _CRT_SECURE_NO_WARNINGS
- #endif
- #ifndef _CRT_NONSTDC_NO_DEPRECATE
- #define _CRT_NONSTDC_NO_DEPRECATE
- #endif
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+#ifndef _CRT_NONSTDC_NO_DEPRECATE
+#define _CRT_NONSTDC_NO_DEPRECATE
+#endif
#endif
#ifndef STBI_WRITE_NO_STDIO
#ifndef STBIW_MALLOC
#define STBIW_MALLOC(sz) malloc(sz)
-#define STBIW_REALLOC(p,newsz) realloc(p,newsz)
+#define STBIW_REALLOC(p, newsz) realloc(p, newsz)
#define STBIW_FREE(p) free(p)
#endif
#ifndef STBIW_REALLOC_SIZED
-#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
+#define STBIW_REALLOC_SIZED(p, oldsz, newsz) STBIW_REALLOC(p, newsz)
#endif
-
#ifndef STBIW_MEMMOVE
-#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
+#define STBIW_MEMMOVE(a, b, sz) memmove(a, b, sz)
#endif
-
#ifndef STBIW_ASSERT
#include <assert.h>
#define STBIW_ASSERT(x) assert(x)
#endif
-#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
+#define STBIW_UCHAR(x) (unsigned char)((x)&0xff)
#ifdef STB_IMAGE_WRITE_STATIC
-static int stbi__flip_vertically_on_write=0;
+static int stbi__flip_vertically_on_write = 0;
static int stbi_write_png_compression_level = 8;
-static int stbi_write_tga_with_rle = 1;
-static int stbi_write_force_png_filter = -1;
+static int stbi_write_tga_with_rle = 1;
+static int stbi_write_force_png_filter = -1;
#else
int stbi_write_png_compression_level = 8;
-int stbi__flip_vertically_on_write=0;
-int stbi_write_tga_with_rle = 1;
-int stbi_write_force_png_filter = -1;
+int stbi__flip_vertically_on_write = 0;
+int stbi_write_tga_with_rle = 1;
+int stbi_write_force_png_filter = -1;
#endif
-STBIWDEF void stbi_flip_vertically_on_write(int flag)
-{
- stbi__flip_vertically_on_write = flag;
-}
+STBIWDEF void stbi_flip_vertically_on_write(int flag) { stbi__flip_vertically_on_write = flag; }
-typedef struct
-{
- stbi_write_func *func;
- void *context;
+typedef struct {
+ stbi_write_func *func;
+ void *context;
} stbi__write_context;
// initialize a callback-based context
-static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
-{
- s->func = c;
- s->context = context;
+static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) {
+ s->func = c;
+ s->context = context;
}
#ifndef STBI_WRITE_NO_STDIO
-static void stbi__stdio_write(void *context, void *data, int size)
-{
- fwrite(data,1,size,(FILE*) context);
-}
+static void stbi__stdio_write(void *context, void *data, int size) { fwrite(data, 1, size, (FILE *)context); }
#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
#ifdef __cplusplus
#else
#define STBIW_EXTERN extern
#endif
-STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
-STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default);
-
-STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
-{
- return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
+STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags,
+ const char *str, int cbmb, wchar_t *widestr,
+ int cchwide);
+STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags,
+ const wchar_t *widestr, int cchwide, char *str,
+ int cbmb, const char *defchar, int *used_default);
+
+STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t *input) {
+ return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int)bufferlen, NULL, NULL);
}
#endif
-static FILE *stbiw__fopen(char const *filename, char const *mode)
-{
- FILE *f;
+static FILE *stbiw__fopen(char const *filename, char const *mode) {
+ FILE *f;
#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
- wchar_t wMode[64];
- wchar_t wFilename[1024];
- if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)))
- return 0;
-
- if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)))
- return 0;
+ wchar_t wMode[64];
+ wchar_t wFilename[1024];
+ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)))
+ return 0;
+
+ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)))
+ return 0;
#if _MSC_VER >= 1400
- if (0 != _wfopen_s(&f, wFilename, wMode))
- f = 0;
+ if (0 != _wfopen_s(&f, wFilename, wMode))
+ f = 0;
#else
- f = _wfopen(wFilename, wMode);
+ f = _wfopen(wFilename, wMode);
#endif
#elif defined(_MSC_VER) && _MSC_VER >= 1400
- if (0 != fopen_s(&f, filename, mode))
- f=0;
+ if (0 != fopen_s(&f, filename, mode))
+ f = 0;
#else
- f = fopen(filename, mode);
+ f = fopen(filename, mode);
#endif
- return f;
+ return f;
}
-static int stbi__start_write_file(stbi__write_context *s, const char *filename)
-{
- FILE *f = stbiw__fopen(filename, "wb");
- stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
- return f != NULL;
+static int stbi__start_write_file(stbi__write_context *s, const char *filename) {
+ FILE *f = stbiw__fopen(filename, "wb");
+ stbi__start_write_callbacks(s, stbi__stdio_write, (void *)f);
+ return f != NULL;
}
-static void stbi__end_write_file(stbi__write_context *s)
-{
- fclose((FILE *)s->context);
-}
+static void stbi__end_write_file(stbi__write_context *s) { fclose((FILE *)s->context); }
#endif // !STBI_WRITE_NO_STDIO
typedef unsigned int stbiw_uint32;
-typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
-
-static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
-{
- while (*fmt) {
- switch (*fmt++) {
- case ' ': break;
- case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
- s->func(s->context,&x,1);
- break; }
- case '2': { int x = va_arg(v,int);
- unsigned char b[2];
- b[0] = STBIW_UCHAR(x);
- b[1] = STBIW_UCHAR(x>>8);
- s->func(s->context,b,2);
- break; }
- case '4': { stbiw_uint32 x = va_arg(v,int);
- unsigned char b[4];
- b[0]=STBIW_UCHAR(x);
- b[1]=STBIW_UCHAR(x>>8);
- b[2]=STBIW_UCHAR(x>>16);
- b[3]=STBIW_UCHAR(x>>24);
- s->func(s->context,b,4);
- break; }
- default:
+typedef int stb_image_write_test[sizeof(stbiw_uint32) == 4 ? 1 : -1];
+
+static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) {
+ while (*fmt) {
+ switch (*fmt++) {
+ case ' ':
+ break;
+ case '1': {
+ unsigned char x = STBIW_UCHAR(va_arg(v, int));
+ s->func(s->context, &x, 1);
+ break;
+ }
+ case '2': {
+ int x = va_arg(v, int);
+ unsigned char b[2];
+ b[0] = STBIW_UCHAR(x);
+ b[1] = STBIW_UCHAR(x >> 8);
+ s->func(s->context, b, 2);
+ break;
+ }
+ case '4': {
+ stbiw_uint32 x = va_arg(v, int);
+ unsigned char b[4];
+ b[0] = STBIW_UCHAR(x);
+ b[1] = STBIW_UCHAR(x >> 8);
+ b[2] = STBIW_UCHAR(x >> 16);
+ b[3] = STBIW_UCHAR(x >> 24);
+ s->func(s->context, b, 4);
+ break;
+ }
+ default:
STBIW_ASSERT(0);
return;
- }
- }
+ }
+ }
}
-static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
-{
- va_list v;
- va_start(v, fmt);
- stbiw__writefv(s, fmt, v);
- va_end(v);
+static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) {
+ va_list v;
+ va_start(v, fmt);
+ stbiw__writefv(s, fmt, v);
+ va_end(v);
}
-static void stbiw__putc(stbi__write_context *s, unsigned char c)
-{
- s->func(s->context, &c, 1);
-}
+static void stbiw__putc(stbi__write_context *s, unsigned char c) { s->func(s->context, &c, 1); }
-static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
-{
- unsigned char arr[3];
- arr[0] = a; arr[1] = b; arr[2] = c;
- s->func(s->context, arr, 3);
+static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) {
+ unsigned char arr[3];
+ arr[0] = a;
+ arr[1] = b;
+ arr[2] = c;
+ s->func(s->context, arr, 3);
}
-static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
-{
- unsigned char bg[3] = { 255, 0, 255}, px[3];
- int k;
+static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono,
+ unsigned char *d) {
+ unsigned char bg[3] = {255, 0, 255}, px[3];
+ int k;
- if (write_alpha < 0)
- s->func(s->context, &d[comp - 1], 1);
+ if (write_alpha < 0)
+ s->func(s->context, &d[comp - 1], 1);
- switch (comp) {
- case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
- case 1:
- if (expand_mono)
+ switch (comp) {
+ case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
+ case 1:
+ if (expand_mono)
stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
- else
- s->func(s->context, d, 1); // monochrome TGA
- break;
- case 4:
- if (!write_alpha) {
+ else
+ s->func(s->context, d, 1); // monochrome TGA
+ break;
+ case 4:
+ if (!write_alpha) {
// composite against pink background
for (k = 0; k < 3; ++k)
- px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
+ px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
break;
- }
- /* FALLTHROUGH */
- case 3:
- stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
- break;
- }
- if (write_alpha > 0)
- s->func(s->context, &d[comp - 1], 1);
+ }
+ /* FALLTHROUGH */
+ case 3:
+ stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
+ break;
+ }
+ if (write_alpha > 0)
+ s->func(s->context, &d[comp - 1], 1);
}
-static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
-{
- stbiw_uint32 zero = 0;
- int i,j, j_end;
-
- if (y <= 0)
- return;
-
- if (stbi__flip_vertically_on_write)
- vdir *= -1;
-
- if (vdir < 0) {
- j_end = -1; j = y-1;
- } else {
- j_end = y; j = 0;
- }
-
- for (; j != j_end; j += vdir) {
- for (i=0; i < x; ++i) {
- unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
- stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
- }
- s->func(s->context, &zero, scanline_pad);
- }
+static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data,
+ int write_alpha, int scanline_pad, int expand_mono) {
+ stbiw_uint32 zero = 0;
+ int i, j, j_end;
+
+ if (y <= 0)
+ return;
+
+ if (stbi__flip_vertically_on_write)
+ vdir *= -1;
+
+ if (vdir < 0) {
+ j_end = -1;
+ j = y - 1;
+ } else {
+ j_end = y;
+ j = 0;
+ }
+
+ for (; j != j_end; j += vdir) {
+ for (i = 0; i < x; ++i) {
+ unsigned char *d = (unsigned char *)data + (j * x + i) * comp;
+ stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
+ }
+ s->func(s->context, &zero, scanline_pad);
+ }
}
-static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
-{
- if (y < 0 || x < 0) {
- return 0;
- } else {
- va_list v;
- va_start(v, fmt);
- stbiw__writefv(s, fmt, v);
- va_end(v);
- stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
- return 1;
- }
+static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono,
+ void *data, int alpha, int pad, const char *fmt, ...) {
+ if (y < 0 || x < 0) {
+ return 0;
+ } else {
+ va_list v;
+ va_start(v, fmt);
+ stbiw__writefv(s, fmt, v);
+ va_end(v);
+ stbiw__write_pixels(s, rgb_dir, vdir, x, y, comp, data, alpha, pad, expand_mono);
+ return 1;
+ }
}
-static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
-{
- int pad = (-x*3) & 3;
- return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
- "11 4 22 4" "4 44 22 444444",
- 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
- 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
+static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) {
+ int pad = (-x * 3) & 3;
+ return stbiw__outfile(s, -1, -1, x, y, comp, 1, (void *)data, 0, pad,
+ "11 4 22 4"
+ "4 44 22 444444",
+ 'B', 'M', 14 + 40 + (x * 3 + pad) * y, 0, 0, 14 + 40, // file header
+ 40, x, y, 1, 24, 0, 0, 0, 0, 0, 0); // bitmap header
}
-STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
-{
- stbi__write_context s;
- stbi__start_write_callbacks(&s, func, context);
- return stbi_write_bmp_core(&s, x, y, comp, data);
+STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) {
+ stbi__write_context s;
+ stbi__start_write_callbacks(&s, func, context);
+ return stbi_write_bmp_core(&s, x, y, comp, data);
}
#ifndef STBI_WRITE_NO_STDIO
-STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
-{
- stbi__write_context s;
- if (stbi__start_write_file(&s,filename)) {
- int r = stbi_write_bmp_core(&s, x, y, comp, data);
- stbi__end_write_file(&s);
- return r;
- } else
- return 0;
+STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) {
+ stbi__write_context s;
+ if (stbi__start_write_file(&s, filename)) {
+ int r = stbi_write_bmp_core(&s, x, y, comp, data);
+ stbi__end_write_file(&s);
+ return r;
+ } else
+ return 0;
}
-#endif //!STBI_WRITE_NO_STDIO
-
-static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
-{
- int has_alpha = (comp == 2 || comp == 4);
- int colorbytes = has_alpha ? comp-1 : comp;
- int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
-
- if (y < 0 || x < 0)
- return 0;
-
- if (!stbi_write_tga_with_rle) {
- return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
- "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
- } else {
- int i,j,k;
- int jend, jdir;
-
- stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8);
-
- if (stbi__flip_vertically_on_write) {
- j = 0;
- jend = y;
- jdir = 1;
- } else {
- j = y-1;
- jend = -1;
- jdir = -1;
- }
- for (; j != jend; j += jdir) {
- unsigned char *row = (unsigned char *) data + j * x * comp;
- int len;
-
- for (i = 0; i < x; i += len) {
- unsigned char *begin = row + i * comp;
- int diff = 1;
- len = 1;
-
- if (i < x - 1) {
- ++len;
- diff = memcmp(begin, row + (i + 1) * comp, comp);
- if (diff) {
- const unsigned char *prev = begin;
- for (k = i + 2; k < x && len < 128; ++k) {
- if (memcmp(prev, row + k * comp, comp)) {
- prev += comp;
- ++len;
- } else {
- --len;
- break;
- }
- }
- } else {
- for (k = i + 2; k < x && len < 128; ++k) {
- if (!memcmp(begin, row + k * comp, comp)) {
- ++len;
- } else {
- break;
- }
- }
- }
- }
-
- if (diff) {
- unsigned char header = STBIW_UCHAR(len - 1);
- s->func(s->context, &header, 1);
- for (k = 0; k < len; ++k) {
- stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
- }
- } else {
- unsigned char header = STBIW_UCHAR(len - 129);
- s->func(s->context, &header, 1);
- stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
+#endif //! STBI_WRITE_NO_STDIO
+
+static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) {
+ int has_alpha = (comp == 2 || comp == 4);
+ int colorbytes = has_alpha ? comp - 1 : comp;
+ int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
+
+ if (y < 0 || x < 0)
+ return 0;
+
+ if (!stbi_write_tga_with_rle) {
+ return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *)data, has_alpha, 0, "111 221 2222 11", 0, 0, format, 0,
+ 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
+ } else {
+ int i, j, k;
+ int jend, jdir;
+
+ stbiw__writef(s, "111 221 2222 11", 0, 0, format + 8, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8,
+ has_alpha * 8);
+
+ if (stbi__flip_vertically_on_write) {
+ j = 0;
+ jend = y;
+ jdir = 1;
+ } else {
+ j = y - 1;
+ jend = -1;
+ jdir = -1;
+ }
+ for (; j != jend; j += jdir) {
+ unsigned char *row = (unsigned char *)data + j * x * comp;
+ int len;
+
+ for (i = 0; i < x; i += len) {
+ unsigned char *begin = row + i * comp;
+ int diff = 1;
+ len = 1;
+
+ if (i < x - 1) {
+ ++len;
+ diff = memcmp(begin, row + (i + 1) * comp, comp);
+ if (diff) {
+ const unsigned char *prev = begin;
+ for (k = i + 2; k < x && len < 128; ++k) {
+ if (memcmp(prev, row + k * comp, comp)) {
+ prev += comp;
+ ++len;
+ } else {
+ --len;
+ break;
+ }
+ }
+ } else {
+ for (k = i + 2; k < x && len < 128; ++k) {
+ if (!memcmp(begin, row + k * comp, comp)) {
+ ++len;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ if (diff) {
+ unsigned char header = STBIW_UCHAR(len - 1);
+ s->func(s->context, &header, 1);
+ for (k = 0; k < len; ++k) {
+ stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
+ }
+ } else {
+ unsigned char header = STBIW_UCHAR(len - 129);
+ s->func(s->context, &header, 1);
+ stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
+ }
}
- }
- }
- }
- return 1;
+ }
+ }
+ return 1;
}
-STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
-{
- stbi__write_context s;
- stbi__start_write_callbacks(&s, func, context);
- return stbi_write_tga_core(&s, x, y, comp, (void *) data);
+STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) {
+ stbi__write_context s;
+ stbi__start_write_callbacks(&s, func, context);
+ return stbi_write_tga_core(&s, x, y, comp, (void *)data);
}
#ifndef STBI_WRITE_NO_STDIO
-STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
-{
- stbi__write_context s;
- if (stbi__start_write_file(&s,filename)) {
- int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
- stbi__end_write_file(&s);
- return r;
- } else
- return 0;
+STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) {
+ stbi__write_context s;
+ if (stbi__start_write_file(&s, filename)) {
+ int r = stbi_write_tga_core(&s, x, y, comp, (void *)data);
+ stbi__end_write_file(&s);
+ return r;
+ } else
+ return 0;
}
#endif
// Radiance RGBE HDR writer
// by Baldur Karlsson
-#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
+#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
-static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
-{
- int exponent;
- float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
+static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) {
+ int exponent;
+ float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
- if (maxcomp < 1e-32f) {
- rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
- } else {
- float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
+ if (maxcomp < 1e-32f) {
+ rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
+ } else {
+ float normalize = (float)frexp(maxcomp, &exponent) * 256.0f / maxcomp;
- rgbe[0] = (unsigned char)(linear[0] * normalize);
- rgbe[1] = (unsigned char)(linear[1] * normalize);
- rgbe[2] = (unsigned char)(linear[2] * normalize);
- rgbe[3] = (unsigned char)(exponent + 128);
- }
+ rgbe[0] = (unsigned char)(linear[0] * normalize);
+ rgbe[1] = (unsigned char)(linear[1] * normalize);
+ rgbe[2] = (unsigned char)(linear[2] * normalize);
+ rgbe[3] = (unsigned char)(exponent + 128);
+ }
}
-static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
-{
- unsigned char lengthbyte = STBIW_UCHAR(length+128);
- STBIW_ASSERT(length+128 <= 255);
- s->func(s->context, &lengthbyte, 1);
- s->func(s->context, &databyte, 1);
+static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) {
+ unsigned char lengthbyte = STBIW_UCHAR(length + 128);
+ STBIW_ASSERT(length + 128 <= 255);
+ s->func(s->context, &lengthbyte, 1);
+ s->func(s->context, &databyte, 1);
}
-static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
-{
- unsigned char lengthbyte = STBIW_UCHAR(length);
- STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
- s->func(s->context, &lengthbyte, 1);
- s->func(s->context, data, length);
+static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) {
+ unsigned char lengthbyte = STBIW_UCHAR(length);
+ STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
+ s->func(s->context, &lengthbyte, 1);
+ s->func(s->context, data, length);
}
-static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
-{
- unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
- unsigned char rgbe[4];
- float linear[3];
- int x;
+static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch,
+ float *scanline) {
+ unsigned char scanlineheader[4] = {2, 2, 0, 0};
+ unsigned char rgbe[4];
+ float linear[3];
+ int x;
- scanlineheader[2] = (width&0xff00)>>8;
- scanlineheader[3] = (width&0x00ff);
+ scanlineheader[2] = (width & 0xff00) >> 8;
+ scanlineheader[3] = (width & 0x00ff);
- /* skip RLE for images too small or large */
- if (width < 8 || width >= 32768) {
- for (x=0; x < width; x++) {
- switch (ncomp) {
+ /* skip RLE for images too small or large */
+ if (width < 8 || width >= 32768) {
+ for (x = 0; x < width; x++) {
+ switch (ncomp) {
case 4: /* fallthrough */
- case 3: linear[2] = scanline[x*ncomp + 2];
- linear[1] = scanline[x*ncomp + 1];
- linear[0] = scanline[x*ncomp + 0];
- break;
+ case 3:
+ linear[2] = scanline[x * ncomp + 2];
+ linear[1] = scanline[x * ncomp + 1];
+ linear[0] = scanline[x * ncomp + 0];
+ break;
default:
- linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
- break;
- }
- stbiw__linear_to_rgbe(rgbe, linear);
- s->func(s->context, rgbe, 4);
- }
- } else {
- int c,r;
- /* encode into scratch buffer */
- for (x=0; x < width; x++) {
- switch(ncomp) {
+ linear[0] = linear[1] = linear[2] = scanline[x * ncomp + 0];
+ break;
+ }
+ stbiw__linear_to_rgbe(rgbe, linear);
+ s->func(s->context, rgbe, 4);
+ }
+ } else {
+ int c, r;
+ /* encode into scratch buffer */
+ for (x = 0; x < width; x++) {
+ switch (ncomp) {
case 4: /* fallthrough */
- case 3: linear[2] = scanline[x*ncomp + 2];
- linear[1] = scanline[x*ncomp + 1];
- linear[0] = scanline[x*ncomp + 0];
- break;
+ case 3:
+ linear[2] = scanline[x * ncomp + 2];
+ linear[1] = scanline[x * ncomp + 1];
+ linear[0] = scanline[x * ncomp + 0];
+ break;
default:
- linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
- break;
- }
- stbiw__linear_to_rgbe(rgbe, linear);
- scratch[x + width*0] = rgbe[0];
- scratch[x + width*1] = rgbe[1];
- scratch[x + width*2] = rgbe[2];
- scratch[x + width*3] = rgbe[3];
- }
-
- s->func(s->context, scanlineheader, 4);
-
- /* RLE each component separately */
- for (c=0; c < 4; c++) {
- unsigned char *comp = &scratch[width*c];
-
- x = 0;
- while (x < width) {
- // find first run
- r = x;
- while (r+2 < width) {
- if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
- break;
- ++r;
- }
- if (r+2 >= width)
- r = width;
- // dump up to first run
- while (x < r) {
- int len = r-x;
- if (len > 128) len = 128;
- stbiw__write_dump_data(s, len, &comp[x]);
- x += len;
+ linear[0] = linear[1] = linear[2] = scanline[x * ncomp + 0];
+ break;
}
- // if there's a run, output it
- if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
- // find next byte after run
- while (r < width && comp[r] == comp[x])
- ++r;
- // output run up to r
- while (x < r) {
- int len = r-x;
- if (len > 127) len = 127;
- stbiw__write_run_data(s, len, comp[x]);
- x += len;
- }
+ stbiw__linear_to_rgbe(rgbe, linear);
+ scratch[x + width * 0] = rgbe[0];
+ scratch[x + width * 1] = rgbe[1];
+ scratch[x + width * 2] = rgbe[2];
+ scratch[x + width * 3] = rgbe[3];
+ }
+
+ s->func(s->context, scanlineheader, 4);
+
+ /* RLE each component separately */
+ for (c = 0; c < 4; c++) {
+ unsigned char *comp = &scratch[width * c];
+
+ x = 0;
+ while (x < width) {
+ // find first run
+ r = x;
+ while (r + 2 < width) {
+ if (comp[r] == comp[r + 1] && comp[r] == comp[r + 2])
+ break;
+ ++r;
+ }
+ if (r + 2 >= width)
+ r = width;
+ // dump up to first run
+ while (x < r) {
+ int len = r - x;
+ if (len > 128)
+ len = 128;
+ stbiw__write_dump_data(s, len, &comp[x]);
+ x += len;
+ }
+ // if there's a run, output it
+ if (r + 2 < width) { // same test as what we break out of in search loop, so only true if we break'd
+ // find next byte after run
+ while (r < width && comp[r] == comp[x])
+ ++r;
+ // output run up to r
+ while (x < r) {
+ int len = r - x;
+ if (len > 127)
+ len = 127;
+ stbiw__write_run_data(s, len, comp[x]);
+ x += len;
+ }
+ }
}
- }
- }
- }
+ }
+ }
}
-static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
-{
- if (y <= 0 || x <= 0 || data == NULL)
- return 0;
- else {
- // Each component is stored separately. Allocate scratch space for full output scanline.
- unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
- int i, len;
- char buffer[128];
- char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
- s->func(s->context, header, sizeof(header)-1);
+static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) {
+ if (y <= 0 || x <= 0 || data == NULL)
+ return 0;
+ else {
+ // Each component is stored separately. Allocate scratch space for full output scanline.
+ unsigned char *scratch = (unsigned char *)STBIW_MALLOC(x * 4);
+ int i, len;
+ char buffer[128];
+ char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
+ s->func(s->context, header, sizeof(header) - 1);
#ifdef __STDC_WANT_SECURE_LIB__
- len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
+ len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
#else
- len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
+ len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
#endif
- s->func(s->context, buffer, len);
-
- for(i=0; i < y; i++)
- stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i));
- STBIW_FREE(scratch);
- return 1;
- }
+ s->func(s->context, buffer, len);
+
+ for (i = 0; i < y; i++)
+ stbiw__write_hdr_scanline(s, x, comp, scratch,
+ data + comp * x * (stbi__flip_vertically_on_write ? y - 1 - i : i));
+ STBIW_FREE(scratch);
+ return 1;
+ }
}
-STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
-{
- stbi__write_context s;
- stbi__start_write_callbacks(&s, func, context);
- return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
+STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) {
+ stbi__write_context s;
+ stbi__start_write_callbacks(&s, func, context);
+ return stbi_write_hdr_core(&s, x, y, comp, (float *)data);
}
#ifndef STBI_WRITE_NO_STDIO
-STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
-{
- stbi__write_context s;
- if (stbi__start_write_file(&s,filename)) {
- int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
- stbi__end_write_file(&s);
- return r;
- } else
- return 0;
+STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) {
+ stbi__write_context s;
+ if (stbi__start_write_file(&s, filename)) {
+ int r = stbi_write_hdr_core(&s, x, y, comp, (float *)data);
+ stbi__end_write_file(&s);
+ return r;
+ } else
+ return 0;
}
#endif // STBI_WRITE_NO_STDIO
-
//////////////////////////////////////////////////////////////////////////////
//
// PNG writer
#ifndef STBIW_ZLIB_COMPRESS
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
-#define stbiw__sbraw(a) ((int *) (a) - 2)
-#define stbiw__sbm(a) stbiw__sbraw(a)[0]
-#define stbiw__sbn(a) stbiw__sbraw(a)[1]
+#define stbiw__sbraw(a) ((int *)(a)-2)
+#define stbiw__sbm(a) stbiw__sbraw(a)[0]
+#define stbiw__sbn(a) stbiw__sbraw(a)[1]
-#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
-#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
-#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
+#define stbiw__sbneedgrow(a, n) ((a) == 0 || stbiw__sbn(a) + n >= stbiw__sbm(a))
+#define stbiw__sbmaybegrow(a, n) (stbiw__sbneedgrow(a, (n)) ? stbiw__sbgrow(a, n) : 0)
+#define stbiw__sbgrow(a, n) stbiw__sbgrowf((void **)&(a), (n), sizeof(*(a)))
-#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
+#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a, 1), (a)[stbiw__sbn(a)++] = (v))
#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
-#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
-
-static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
-{
- int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
- void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
- STBIW_ASSERT(p);
- if (p) {
- if (!*arr) ((int *) p)[1] = 0;
- *arr = (void *) ((int *) p + 2);
- stbiw__sbm(*arr) = m;
- }
- return *arr;
+#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)), 0 : 0)
+
+static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) {
+ int m = *arr ? 2 * stbiw__sbm(*arr) + increment : increment + 1;
+ void *p =
+ STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr) * itemsize + sizeof(int) * 2) : 0,
+ itemsize * m + sizeof(int) * 2);
+ STBIW_ASSERT(p);
+ if (p) {
+ if (!*arr)
+ ((int *)p)[1] = 0;
+ *arr = (void *)((int *)p + 2);
+ stbiw__sbm(*arr) = m;
+ }
+ return *arr;
}
-static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
-{
- while (*bitcount >= 8) {
- stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
- *bitbuffer >>= 8;
- *bitcount -= 8;
- }
- return data;
+static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) {
+ while (*bitcount >= 8) {
+ stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
+ *bitbuffer >>= 8;
+ *bitcount -= 8;
+ }
+ return data;
}
-static int stbiw__zlib_bitrev(int code, int codebits)
-{
- int res=0;
- while (codebits--) {
- res = (res << 1) | (code & 1);
- code >>= 1;
- }
- return res;
+static int stbiw__zlib_bitrev(int code, int codebits) {
+ int res = 0;
+ while (codebits--) {
+ res = (res << 1) | (code & 1);
+ code >>= 1;
+ }
+ return res;
}
-static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
-{
- int i;
- for (i=0; i < limit && i < 258; ++i)
- if (a[i] != b[i]) break;
- return i;
+static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) {
+ int i;
+ for (i = 0; i < limit && i < 258; ++i)
+ if (a[i] != b[i])
+ break;
+ return i;
}
-static unsigned int stbiw__zhash(unsigned char *data)
-{
- stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 4;
- hash += hash >> 17;
- hash ^= hash << 25;
- hash += hash >> 6;
- return hash;
+static unsigned int stbiw__zhash(unsigned char *data) {
+ stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+ return hash;
}
-#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
-#define stbiw__zlib_add(code,codebits) \
- (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
-#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
+#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
+#define stbiw__zlib_add(code, codebits) (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
+#define stbiw__zlib_huffa(b, c) stbiw__zlib_add(stbiw__zlib_bitrev(b, c), c)
// default huffman tables
-#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
-#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
-#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
-#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
-#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n))
+#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
+#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
+#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256, 7)
+#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280, 8)
+#define stbiw__zlib_huff(n) \
+ ((n) <= 143 ? stbiw__zlib_huff1(n) \
+ : (n) <= 255 ? stbiw__zlib_huff2(n) \
+ : (n) <= 279 ? stbiw__zlib_huff3(n) \
+ : stbiw__zlib_huff4(n))
#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
-#define stbiw__ZHASH 16384
+#define stbiw__ZHASH 16384
#endif // STBIW_ZLIB_COMPRESS
-STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
-{
+STBIWDEF unsigned char *stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) {
#ifdef STBIW_ZLIB_COMPRESS
- // user provided a zlib compress implementation, use that
- return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
-#else // use builtin
- static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 };
- static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 };
- static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 };
- static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 };
- unsigned int bitbuf=0;
- int i,j, bitcount=0;
- unsigned char *out = NULL;
- unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**));
- if (hash_table == NULL)
- return NULL;
- if (quality < 5) quality = 5;
-
- stbiw__sbpush(out, 0x78); // DEFLATE 32K window
- stbiw__sbpush(out, 0x5e); // FLEVEL = 1
- stbiw__zlib_add(1,1); // BFINAL = 1
- stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman
-
- for (i=0; i < stbiw__ZHASH; ++i)
- hash_table[i] = NULL;
-
- i=0;
- while (i < data_len-3) {
- // hash next 3 bytes of data to be compressed
- int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
- unsigned char *bestloc = 0;
- unsigned char **hlist = hash_table[h];
- int n = stbiw__sbcount(hlist);
- for (j=0; j < n; ++j) {
- if (hlist[j]-data > i-32768) { // if entry lies within window
- int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
- if (d >= best) { best=d; bestloc=hlist[j]; }
- }
- }
- // when hash table entry is too long, delete half the entries
- if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
- STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
- stbiw__sbn(hash_table[h]) = quality;
- }
- stbiw__sbpush(hash_table[h],data+i);
-
- if (bestloc) {
- // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
- h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
- hlist = hash_table[h];
- n = stbiw__sbcount(hlist);
- for (j=0; j < n; ++j) {
- if (hlist[j]-data > i-32767) {
- int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
- if (e > best) { // if next match is better, bail on current match
- bestloc = NULL;
- break;
- }
+ // user provided a zlib compress implementation, use that
+ return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
+#else // use builtin
+ static unsigned short lengthc[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
+ 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 259};
+ static unsigned char lengtheb[] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2,
+ 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
+ static unsigned short distc[] = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33,
+ 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
+ 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32768};
+ static unsigned char disteb[] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
+ 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
+ unsigned int bitbuf = 0;
+ int i, j, bitcount = 0;
+ unsigned char *out = NULL;
+ unsigned char ***hash_table = (unsigned char ***)STBIW_MALLOC(stbiw__ZHASH * sizeof(char **));
+ if (hash_table == NULL)
+ return NULL;
+ if (quality < 5)
+ quality = 5;
+
+ stbiw__sbpush(out, 0x78); // DEFLATE 32K window
+ stbiw__sbpush(out, 0x5e); // FLEVEL = 1
+ stbiw__zlib_add(1, 1); // BFINAL = 1
+ stbiw__zlib_add(1, 2); // BTYPE = 1 -- fixed huffman
+
+ for (i = 0; i < stbiw__ZHASH; ++i)
+ hash_table[i] = NULL;
+
+ i = 0;
+ while (i < data_len - 3) {
+ // hash next 3 bytes of data to be compressed
+ int h = stbiw__zhash(data + i) & (stbiw__ZHASH - 1), best = 3;
+ unsigned char *bestloc = 0;
+ unsigned char **hlist = hash_table[h];
+ int n = stbiw__sbcount(hlist);
+ for (j = 0; j < n; ++j) {
+ if (hlist[j] - data > i - 32768) { // if entry lies within window
+ int d = stbiw__zlib_countm(hlist[j], data + i, data_len - i);
+ if (d >= best) {
+ best = d;
+ bestloc = hlist[j];
+ }
+ }
+ }
+ // when hash table entry is too long, delete half the entries
+ if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2 * quality) {
+ STBIW_MEMMOVE(hash_table[h], hash_table[h] + quality, sizeof(hash_table[h][0]) * quality);
+ stbiw__sbn(hash_table[h]) = quality;
+ }
+ stbiw__sbpush(hash_table[h], data + i);
+
+ if (bestloc) {
+ // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
+ h = stbiw__zhash(data + i + 1) & (stbiw__ZHASH - 1);
+ hlist = hash_table[h];
+ n = stbiw__sbcount(hlist);
+ for (j = 0; j < n; ++j) {
+ if (hlist[j] - data > i - 32767) {
+ int e = stbiw__zlib_countm(hlist[j], data + i + 1, data_len - i - 1);
+ if (e > best) { // if next match is better, bail on current match
+ bestloc = NULL;
+ break;
+ }
+ }
+ }
+ }
+
+ if (bestloc) {
+ int d = (int)(data + i - bestloc); // distance back
+ STBIW_ASSERT(d <= 32767 && best <= 258);
+ for (j = 0; best > lengthc[j + 1] - 1; ++j)
+ ;
+ stbiw__zlib_huff(j + 257);
+ if (lengtheb[j])
+ stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
+ for (j = 0; d > distc[j + 1] - 1; ++j)
+ ;
+ stbiw__zlib_add(stbiw__zlib_bitrev(j, 5), 5);
+ if (disteb[j])
+ stbiw__zlib_add(d - distc[j], disteb[j]);
+ i += best;
+ } else {
+ stbiw__zlib_huffb(data[i]);
+ ++i;
+ }
+ }
+ // write out final bytes
+ for (; i < data_len; ++i)
+ stbiw__zlib_huffb(data[i]);
+ stbiw__zlib_huff(256); // end of block
+ // pad with 0 bits to byte boundary
+ while (bitcount)
+ stbiw__zlib_add(0, 1);
+
+ for (i = 0; i < stbiw__ZHASH; ++i)
+ (void)stbiw__sbfree(hash_table[i]);
+ STBIW_FREE(hash_table);
+
+ {
+ // compute adler32 on input
+ unsigned int s1 = 1, s2 = 0;
+ int blocklen = (int)(data_len % 5552);
+ j = 0;
+ while (j < data_len) {
+ for (i = 0; i < blocklen; ++i) {
+ s1 += data[j + i];
+ s2 += s1;
}
- }
- }
-
- if (bestloc) {
- int d = (int) (data+i - bestloc); // distance back
- STBIW_ASSERT(d <= 32767 && best <= 258);
- for (j=0; best > lengthc[j+1]-1; ++j);
- stbiw__zlib_huff(j+257);
- if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
- for (j=0; d > distc[j+1]-1; ++j);
- stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
- if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
- i += best;
- } else {
- stbiw__zlib_huffb(data[i]);
- ++i;
- }
- }
- // write out final bytes
- for (;i < data_len; ++i)
- stbiw__zlib_huffb(data[i]);
- stbiw__zlib_huff(256); // end of block
- // pad with 0 bits to byte boundary
- while (bitcount)
- stbiw__zlib_add(0,1);
-
- for (i=0; i < stbiw__ZHASH; ++i)
- (void) stbiw__sbfree(hash_table[i]);
- STBIW_FREE(hash_table);
-
- {
- // compute adler32 on input
- unsigned int s1=1, s2=0;
- int blocklen = (int) (data_len % 5552);
- j=0;
- while (j < data_len) {
- for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
- s1 %= 65521; s2 %= 65521;
- j += blocklen;
- blocklen = 5552;
- }
- stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
- stbiw__sbpush(out, STBIW_UCHAR(s2));
- stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
- stbiw__sbpush(out, STBIW_UCHAR(s1));
- }
- *out_len = stbiw__sbn(out);
- // make returned pointer freeable
- STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
- return (unsigned char *) stbiw__sbraw(out);
+ s1 %= 65521;
+ s2 %= 65521;
+ j += blocklen;
+ blocklen = 5552;
+ }
+ stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
+ stbiw__sbpush(out, STBIW_UCHAR(s2));
+ stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
+ stbiw__sbpush(out, STBIW_UCHAR(s1));
+ }
+ *out_len = stbiw__sbn(out);
+ // make returned pointer freeable
+ STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
+ return (unsigned char *)stbiw__sbraw(out);
#endif // STBIW_ZLIB_COMPRESS
}
-static unsigned int stbiw__crc32(unsigned char *buffer, int len)
-{
+static unsigned int stbiw__crc32(unsigned char *buffer, int len) {
#ifdef STBIW_CRC32
return STBIW_CRC32(buffer, len);
#else
- static unsigned int crc_table[256] =
- {
- 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
- 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
- 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
- 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
- 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
- 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
- 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
- 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
- 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
- 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
- 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
- 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
- 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
- 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
- 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
- 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
- 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
- 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
- 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
- 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
- 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
- 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
- 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
- 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
- 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
- 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
- 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
- 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
- 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
- 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
- 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
- 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
- };
-
- unsigned int crc = ~0u;
- int i;
- for (i=0; i < len; ++i)
- crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
- return ~crc;
+ static unsigned int crc_table[256] = {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0eDB8832,
+ 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
+ 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A,
+ 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
+ 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
+ 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
+ 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4,
+ 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
+ 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
+ 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525,
+ 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
+ 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
+ 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76,
+ 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
+ 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6,
+ 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
+ 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
+ 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7,
+ 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
+ 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
+ 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330,
+ 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
+
+ unsigned int crc = ~0u;
+ int i;
+ for (i = 0; i < len; ++i)
+ crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
+ return ~crc;
#endif
}
-#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4)
-#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
-#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
+#define stbiw__wpng4(o, a, b, c, d) \
+ ((o)[0] = STBIW_UCHAR(a), (o)[1] = STBIW_UCHAR(b), (o)[2] = STBIW_UCHAR(c), (o)[3] = STBIW_UCHAR(d), (o) += 4)
+#define stbiw__wp32(data, v) stbiw__wpng4(data, (v) >> 24, (v) >> 16, (v) >> 8, (v));
+#define stbiw__wptag(data, s) stbiw__wpng4(data, s[0], s[1], s[2], s[3])
-static void stbiw__wpcrc(unsigned char **data, int len)
-{
- unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
- stbiw__wp32(*data, crc);
+static void stbiw__wpcrc(unsigned char **data, int len) {
+ unsigned int crc = stbiw__crc32(*data - len - 4, len + 4);
+ stbiw__wp32(*data, crc);
}
-static unsigned char stbiw__paeth(int a, int b, int c)
-{
- int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
- if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
- if (pb <= pc) return STBIW_UCHAR(b);
- return STBIW_UCHAR(c);
+static unsigned char stbiw__paeth(int a, int b, int c) {
+ int p = a + b - c, pa = abs(p - a), pb = abs(p - b), pc = abs(p - c);
+ if (pa <= pb && pa <= pc)
+ return STBIW_UCHAR(a);
+ if (pb <= pc)
+ return STBIW_UCHAR(b);
+ return STBIW_UCHAR(c);
}
// @OPTIMIZE: provide an option that always forces left-predict or paeth predict
-static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer)
-{
- static int mapping[] = { 0,1,2,3,4 };
- static int firstmap[] = { 0,1,0,5,6 };
- int *mymap = (y != 0) ? mapping : firstmap;
- int i;
- int type = mymap[filter_type];
- unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
- int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
-
- if (type==0) {
- memcpy(line_buffer, z, width*n);
- return;
- }
-
- // first loop isn't optimized since it's just one pixel
- for (i = 0; i < n; ++i) {
- switch (type) {
- case 1: line_buffer[i] = z[i]; break;
- case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break;
- case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break;
- case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break;
- case 5: line_buffer[i] = z[i]; break;
- case 6: line_buffer[i] = z[i]; break;
- }
- }
- switch (type) {
- case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break;
- case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break;
- case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break;
- case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break;
- case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break;
- case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
- }
+static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n,
+ int filter_type, signed char *line_buffer) {
+ static int mapping[] = {0, 1, 2, 3, 4};
+ static int firstmap[] = {0, 1, 0, 5, 6};
+ int *mymap = (y != 0) ? mapping : firstmap;
+ int i;
+ int type = mymap[filter_type];
+ unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height - 1 - y : y);
+ int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
+
+ if (type == 0) {
+ memcpy(line_buffer, z, width * n);
+ return;
+ }
+
+ // first loop isn't optimized since it's just one pixel
+ for (i = 0; i < n; ++i) {
+ switch (type) {
+ case 1:
+ line_buffer[i] = z[i];
+ break;
+ case 2:
+ line_buffer[i] = z[i] - z[i - signed_stride];
+ break;
+ case 3:
+ line_buffer[i] = z[i] - (z[i - signed_stride] >> 1);
+ break;
+ case 4:
+ line_buffer[i] = (signed char)(z[i] - stbiw__paeth(0, z[i - signed_stride], 0));
+ break;
+ case 5:
+ line_buffer[i] = z[i];
+ break;
+ case 6:
+ line_buffer[i] = z[i];
+ break;
+ }
+ }
+ switch (type) {
+ case 1:
+ for (i = n; i < width * n; ++i)
+ line_buffer[i] = z[i] - z[i - n];
+ break;
+ case 2:
+ for (i = n; i < width * n; ++i)
+ line_buffer[i] = z[i] - z[i - signed_stride];
+ break;
+ case 3:
+ for (i = n; i < width * n; ++i)
+ line_buffer[i] = z[i] - ((z[i - n] + z[i - signed_stride]) >> 1);
+ break;
+ case 4:
+ for (i = n; i < width * n; ++i)
+ line_buffer[i] = z[i] - stbiw__paeth(z[i - n], z[i - signed_stride], z[i - signed_stride - n]);
+ break;
+ case 5:
+ for (i = n; i < width * n; ++i)
+ line_buffer[i] = z[i] - (z[i - n] >> 1);
+ break;
+ case 6:
+ for (i = n; i < width * n; ++i)
+ line_buffer[i] = z[i] - stbiw__paeth(z[i - n], 0, 0);
+ break;
+ }
}
-STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
-{
- int force_filter = stbi_write_force_png_filter;
- int ctype[5] = { -1, 0, 4, 2, 6 };
- unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
- unsigned char *out,*o, *filt, *zlib;
- signed char *line_buffer;
- int j,zlen;
-
- if (stride_bytes == 0)
- stride_bytes = x * n;
-
- if (force_filter >= 5) {
- force_filter = -1;
- }
-
- filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
- line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
- for (j=0; j < y; ++j) {
- int filter_type;
- if (force_filter > -1) {
- filter_type = force_filter;
- stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
- } else { // Estimate the best filter by running through all of them:
- int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
- for (filter_type = 0; filter_type < 5; filter_type++) {
- stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
-
- // Estimate the entropy of the line using this filter; the less, the better.
- est = 0;
- for (i = 0; i < x*n; ++i) {
- est += abs((signed char) line_buffer[i]);
+STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n,
+ int *out_len) {
+ int force_filter = stbi_write_force_png_filter;
+ int ctype[5] = {-1, 0, 4, 2, 6};
+ unsigned char sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+ unsigned char *out, *o, *filt, *zlib;
+ signed char *line_buffer;
+ int j, zlen;
+
+ if (stride_bytes == 0)
+ stride_bytes = x * n;
+
+ if (force_filter >= 5) {
+ force_filter = -1;
+ }
+
+ filt = (unsigned char *)STBIW_MALLOC((x * n + 1) * y);
+ if (!filt)
+ return 0;
+ line_buffer = (signed char *)STBIW_MALLOC(x * n);
+ if (!line_buffer) {
+ STBIW_FREE(filt);
+ return 0;
+ }
+ for (j = 0; j < y; ++j) {
+ int filter_type;
+ if (force_filter > -1) {
+ filter_type = force_filter;
+ stbiw__encode_png_line((unsigned char *)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
+ } else { // Estimate the best filter by running through all of them:
+ int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
+ for (filter_type = 0; filter_type < 5; filter_type++) {
+ stbiw__encode_png_line((unsigned char *)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
+
+ // Estimate the entropy of the line using this filter; the less, the better.
+ est = 0;
+ for (i = 0; i < x * n; ++i) {
+ est += abs((signed char)line_buffer[i]);
+ }
+ if (est < best_filter_val) {
+ best_filter_val = est;
+ best_filter = filter_type;
+ }
}
- if (est < best_filter_val) {
- best_filter_val = est;
- best_filter = filter_type;
+ if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it
+ stbiw__encode_png_line((unsigned char *)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
+ filter_type = best_filter;
}
- }
- if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it
- stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
- filter_type = best_filter;
- }
- }
- // when we get here, filter_type contains the filter type, and line_buffer contains the data
- filt[j*(x*n+1)] = (unsigned char) filter_type;
- STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
- }
- STBIW_FREE(line_buffer);
- zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level);
- STBIW_FREE(filt);
- if (!zlib) return 0;
-
- // each tag requires 12 bytes of overhead
- out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
- if (!out) return 0;
- *out_len = 8 + 12+13 + 12+zlen + 12;
-
- o=out;
- STBIW_MEMMOVE(o,sig,8); o+= 8;
- stbiw__wp32(o, 13); // header length
- stbiw__wptag(o, "IHDR");
- stbiw__wp32(o, x);
- stbiw__wp32(o, y);
- *o++ = 8;
- *o++ = STBIW_UCHAR(ctype[n]);
- *o++ = 0;
- *o++ = 0;
- *o++ = 0;
- stbiw__wpcrc(&o,13);
-
- stbiw__wp32(o, zlen);
- stbiw__wptag(o, "IDAT");
- STBIW_MEMMOVE(o, zlib, zlen);
- o += zlen;
- STBIW_FREE(zlib);
- stbiw__wpcrc(&o, zlen);
-
- stbiw__wp32(o,0);
- stbiw__wptag(o, "IEND");
- stbiw__wpcrc(&o,0);
-
- STBIW_ASSERT(o == out + *out_len);
-
- return out;
+ }
+ // when we get here, filter_type contains the filter type, and line_buffer contains the data
+ filt[j * (x * n + 1)] = (unsigned char)filter_type;
+ STBIW_MEMMOVE(filt + j * (x * n + 1) + 1, line_buffer, x * n);
+ }
+ STBIW_FREE(line_buffer);
+ zlib = stbi_zlib_compress(filt, y * (x * n + 1), &zlen, stbi_write_png_compression_level);
+ STBIW_FREE(filt);
+ if (!zlib)
+ return 0;
+
+ // each tag requires 12 bytes of overhead
+ out = (unsigned char *)STBIW_MALLOC(8 + 12 + 13 + 12 + zlen + 12);
+ if (!out)
+ return 0;
+ *out_len = 8 + 12 + 13 + 12 + zlen + 12;
+
+ o = out;
+ STBIW_MEMMOVE(o, sig, 8);
+ o += 8;
+ stbiw__wp32(o, 13); // header length
+ stbiw__wptag(o, "IHDR");
+ stbiw__wp32(o, x);
+ stbiw__wp32(o, y);
+ *o++ = 8;
+ *o++ = STBIW_UCHAR(ctype[n]);
+ *o++ = 0;
+ *o++ = 0;
+ *o++ = 0;
+ stbiw__wpcrc(&o, 13);
+
+ stbiw__wp32(o, zlen);
+ stbiw__wptag(o, "IDAT");
+ STBIW_MEMMOVE(o, zlib, zlen);
+ o += zlen;
+ STBIW_FREE(zlib);
+ stbiw__wpcrc(&o, zlen);
+
+ stbiw__wp32(o, 0);
+ stbiw__wptag(o, "IEND");
+ stbiw__wpcrc(&o, 0);
+
+ STBIW_ASSERT(o == out + *out_len);
+
+ return out;
}
#ifndef STBI_WRITE_NO_STDIO
-STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
-{
- FILE *f;
- int len;
- unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
- if (png == NULL) return 0;
-
- f = stbiw__fopen(filename, "wb");
- if (!f) { STBIW_FREE(png); return 0; }
- fwrite(png, 1, len, f);
- fclose(f);
- STBIW_FREE(png);
- return 1;
+STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) {
+ FILE *f;
+ int len;
+ unsigned char *png = stbi_write_png_to_mem((const unsigned char *)data, stride_bytes, x, y, comp, &len);
+ if (png == NULL)
+ return 0;
+
+ f = stbiw__fopen(filename, "wb");
+ if (!f) {
+ STBIW_FREE(png);
+ return 0;
+ }
+ fwrite(png, 1, len, f);
+ fclose(f);
+ STBIW_FREE(png);
+ return 1;
}
#endif
-STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes)
-{
- int len;
- unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
- if (png == NULL) return 0;
- func(context, png, len);
- STBIW_FREE(png);
- return 1;
+STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data,
+ int stride_bytes) {
+ int len;
+ unsigned char *png = stbi_write_png_to_mem((const unsigned char *)data, stride_bytes, x, y, comp, &len);
+ if (png == NULL)
+ return 0;
+ func(context, png, len);
+ STBIW_FREE(png);
+ return 1;
}
-
/* ***************************************************************************
*
* JPEG writer
* public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html
*/
-static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,
- 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 };
+static const unsigned char stbiw__jpg_ZigZag[] = {0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42,
+ 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53,
+ 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60,
+ 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63};
static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) {
- int bitBuf = *bitBufP, bitCnt = *bitCntP;
- bitCnt += bs[1];
- bitBuf |= bs[0] << (24 - bitCnt);
- while(bitCnt >= 8) {
- unsigned char c = (bitBuf >> 16) & 255;
- stbiw__putc(s, c);
- if(c == 255) {
- stbiw__putc(s, 0);
- }
- bitBuf <<= 8;
- bitCnt -= 8;
- }
- *bitBufP = bitBuf;
- *bitCntP = bitCnt;
+ int bitBuf = *bitBufP, bitCnt = *bitCntP;
+ bitCnt += bs[1];
+ bitBuf |= bs[0] << (24 - bitCnt);
+ while (bitCnt >= 8) {
+ unsigned char c = (bitBuf >> 16) & 255;
+ stbiw__putc(s, c);
+ if (c == 255) {
+ stbiw__putc(s, 0);
+ }
+ bitBuf <<= 8;
+ bitCnt -= 8;
+ }
+ *bitBufP = bitBuf;
+ *bitCntP = bitCnt;
}
-static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) {
- float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
- float z1, z2, z3, z4, z5, z11, z13;
-
- float tmp0 = d0 + d7;
- float tmp7 = d0 - d7;
- float tmp1 = d1 + d6;
- float tmp6 = d1 - d6;
- float tmp2 = d2 + d5;
- float tmp5 = d2 - d5;
- float tmp3 = d3 + d4;
- float tmp4 = d3 - d4;
-
- // Even part
- float tmp10 = tmp0 + tmp3; // phase 2
- float tmp13 = tmp0 - tmp3;
- float tmp11 = tmp1 + tmp2;
- float tmp12 = tmp1 - tmp2;
-
- d0 = tmp10 + tmp11; // phase 3
- d4 = tmp10 - tmp11;
-
- z1 = (tmp12 + tmp13) * 0.707106781f; // c4
- d2 = tmp13 + z1; // phase 5
- d6 = tmp13 - z1;
-
- // Odd part
- tmp10 = tmp4 + tmp5; // phase 2
- tmp11 = tmp5 + tmp6;
- tmp12 = tmp6 + tmp7;
-
- // The rotator is modified from fig 4-8 to avoid extra negations.
- z5 = (tmp10 - tmp12) * 0.382683433f; // c6
- z2 = tmp10 * 0.541196100f + z5; // c2-c6
- z4 = tmp12 * 1.306562965f + z5; // c2+c6
- z3 = tmp11 * 0.707106781f; // c4
-
- z11 = tmp7 + z3; // phase 5
- z13 = tmp7 - z3;
-
- *d5p = z13 + z2; // phase 6
- *d3p = z13 - z2;
- *d1p = z11 + z4;
- *d7p = z11 - z4;
-
- *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6;
+static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p,
+ float *d7p) {
+ float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
+ float z1, z2, z3, z4, z5, z11, z13;
+
+ float tmp0 = d0 + d7;
+ float tmp7 = d0 - d7;
+ float tmp1 = d1 + d6;
+ float tmp6 = d1 - d6;
+ float tmp2 = d2 + d5;
+ float tmp5 = d2 - d5;
+ float tmp3 = d3 + d4;
+ float tmp4 = d3 - d4;
+
+ // Even part
+ float tmp10 = tmp0 + tmp3; // phase 2
+ float tmp13 = tmp0 - tmp3;
+ float tmp11 = tmp1 + tmp2;
+ float tmp12 = tmp1 - tmp2;
+
+ d0 = tmp10 + tmp11; // phase 3
+ d4 = tmp10 - tmp11;
+
+ z1 = (tmp12 + tmp13) * 0.707106781f; // c4
+ d2 = tmp13 + z1; // phase 5
+ d6 = tmp13 - z1;
+
+ // Odd part
+ tmp10 = tmp4 + tmp5; // phase 2
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ // The rotator is modified from fig 4-8 to avoid extra negations.
+ z5 = (tmp10 - tmp12) * 0.382683433f; // c6
+ z2 = tmp10 * 0.541196100f + z5; // c2-c6
+ z4 = tmp12 * 1.306562965f + z5; // c2+c6
+ z3 = tmp11 * 0.707106781f; // c4
+
+ z11 = tmp7 + z3; // phase 5
+ z13 = tmp7 - z3;
+
+ *d5p = z13 + z2; // phase 6
+ *d3p = z13 - z2;
+ *d1p = z11 + z4;
+ *d7p = z11 - z4;
+
+ *d0p = d0;
+ *d2p = d2;
+ *d4p = d4;
+ *d6p = d6;
}
static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
- int tmp1 = val < 0 ? -val : val;
- val = val < 0 ? val-1 : val;
- bits[1] = 1;
- while(tmp1 >>= 1) {
- ++bits[1];
- }
- bits[0] = val & ((1<<bits[1])-1);
+ int tmp1 = val < 0 ? -val : val;
+ val = val < 0 ? val - 1 : val;
+ bits[1] = 1;
+ while (tmp1 >>= 1) {
+ ++bits[1];
+ }
+ bits[0] = val & ((1 << bits[1]) - 1);
}
-static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
- const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
- const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
- int dataOff, i, diff, end0pos;
- int DU[64];
-
- // DCT rows
- for(dataOff=0; dataOff<64; dataOff+=8) {
- stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]);
- }
- // DCT columns
- for(dataOff=0; dataOff<8; ++dataOff) {
- stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+8], &CDU[dataOff+16], &CDU[dataOff+24], &CDU[dataOff+32], &CDU[dataOff+40], &CDU[dataOff+48], &CDU[dataOff+56]);
- }
- // Quantize/descale/zigzag the coefficients
- for(i=0; i<64; ++i) {
- float v = CDU[i]*fdtbl[i];
- // DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
- // ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
- DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
- }
-
- // Encode DC
- diff = DU[0] - DC;
- if (diff == 0) {
- stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
- } else {
- unsigned short bits[2];
- stbiw__jpg_calcBits(diff, bits);
- stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
- stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
- }
- // Encode ACs
- end0pos = 63;
- for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
- }
- // end0pos = first element in reverse order !=0
- if(end0pos == 0) {
- stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
- return DU[0];
- }
- for(i = 1; i <= end0pos; ++i) {
- int startpos = i;
- int nrzeroes;
- unsigned short bits[2];
- for (; DU[i]==0 && i<=end0pos; ++i) {
- }
- nrzeroes = i-startpos;
- if ( nrzeroes >= 16 ) {
- int lng = nrzeroes>>4;
- int nrmarker;
- for (nrmarker=1; nrmarker <= lng; ++nrmarker)
- stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
- nrzeroes &= 15;
- }
- stbiw__jpg_calcBits(DU[i], bits);
- stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
- stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
- }
- if(end0pos != 63) {
- stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
- }
- return DU[0];
+static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, float *fdtbl, int DC,
+ const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
+ const unsigned short EOB[2] = {HTAC[0x00][0], HTAC[0x00][1]};
+ const unsigned short M16zeroes[2] = {HTAC[0xF0][0], HTAC[0xF0][1]};
+ int dataOff, i, diff, end0pos;
+ int DU[64];
+
+ // DCT rows
+ for (dataOff = 0; dataOff < 64; dataOff += 8) {
+ stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff + 1], &CDU[dataOff + 2], &CDU[dataOff + 3], &CDU[dataOff + 4],
+ &CDU[dataOff + 5], &CDU[dataOff + 6], &CDU[dataOff + 7]);
+ }
+ // DCT columns
+ for (dataOff = 0; dataOff < 8; ++dataOff) {
+ stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff + 8], &CDU[dataOff + 16], &CDU[dataOff + 24], &CDU[dataOff + 32],
+ &CDU[dataOff + 40], &CDU[dataOff + 48], &CDU[dataOff + 56]);
+ }
+ // Quantize/descale/zigzag the coefficients
+ for (i = 0; i < 64; ++i) {
+ float v = CDU[i] * fdtbl[i];
+ // DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
+ // ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
+ DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
+ }
+
+ // Encode DC
+ diff = DU[0] - DC;
+ if (diff == 0) {
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
+ } else {
+ unsigned short bits[2];
+ stbiw__jpg_calcBits(diff, bits);
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
+ }
+ // Encode ACs
+ end0pos = 63;
+ for (; (end0pos > 0) && (DU[end0pos] == 0); --end0pos) {
+ }
+ // end0pos = first element in reverse order !=0
+ if (end0pos == 0) {
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
+ return DU[0];
+ }
+ for (i = 1; i <= end0pos; ++i) {
+ int startpos = i;
+ int nrzeroes;
+ unsigned short bits[2];
+ for (; DU[i] == 0 && i <= end0pos; ++i) {
+ }
+ nrzeroes = i - startpos;
+ if (nrzeroes >= 16) {
+ int lng = nrzeroes >> 4;
+ int nrmarker;
+ for (nrmarker = 1; nrmarker <= lng; ++nrmarker)
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
+ nrzeroes &= 15;
+ }
+ stbiw__jpg_calcBits(DU[i], bits);
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes << 4) + bits[1]]);
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
+ }
+ if (end0pos != 63) {
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
+ }
+ return DU[0];
}
-static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) {
- // Constants that don't pollute global namespace
- static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};
- static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
- static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d};
- static const unsigned char std_ac_luminance_values[] = {
- 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
- 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
- 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
- 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
- 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
- 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
- 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
- };
- static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
- static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
- static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};
- static const unsigned char std_ac_chrominance_values[] = {
- 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
- 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
- 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
- 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
- 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
- 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
- 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
- };
- // Huffman tables
- static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}};
- static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}};
- static const unsigned short YAC_HT[256][2] = {
- {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0},
- {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
- };
- static const unsigned short UVAC_HT[256][2] = {
- {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0},
- {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
- };
- static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22,
- 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99};
- static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99,
- 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
- static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
- 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
-
- int row, col, i, k;
- float fdtbl_Y[64], fdtbl_UV[64];
- unsigned char YTable[64], UVTable[64];
-
- if(!data || !width || !height || comp > 4 || comp < 1) {
- return 0;
- }
-
- quality = quality ? quality : 90;
- quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
- quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
-
- for(i = 0; i < 64; ++i) {
- int uvti, yti = (YQT[i]*quality+50)/100;
- YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
- uvti = (UVQT[i]*quality+50)/100;
- UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
- }
-
- for(row = 0, k = 0; row < 8; ++row) {
- for(col = 0; col < 8; ++col, ++k) {
- fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
- fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
- }
- }
-
- // Write Headers
- {
- static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 };
- static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
- const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
- 3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
- s->func(s->context, (void*)head0, sizeof(head0));
- s->func(s->context, (void*)YTable, sizeof(YTable));
- stbiw__putc(s, 1);
- s->func(s->context, UVTable, sizeof(UVTable));
- s->func(s->context, (void*)head1, sizeof(head1));
- s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1);
- s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values));
- stbiw__putc(s, 0x10); // HTYACinfo
- s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1);
- s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values));
- stbiw__putc(s, 1); // HTUDCinfo
- s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1);
- s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values));
- stbiw__putc(s, 0x11); // HTUACinfo
- s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1);
- s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values));
- s->func(s->context, (void*)head2, sizeof(head2));
- }
-
- // Encode 8x8 macroblocks
- {
- static const unsigned short fillBits[] = {0x7F, 7};
- const unsigned char *imageData = (const unsigned char *)data;
- int DCY=0, DCU=0, DCV=0;
- int bitBuf=0, bitCnt=0;
- // comp == 2 is grey+alpha (alpha is ignored)
- int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
- int x, y, pos;
- for(y = 0; y < height; y += 8) {
- for(x = 0; x < width; x += 8) {
- float YDU[64], UDU[64], VDU[64];
- for(row = y, pos = 0; row < y+8; ++row) {
- // row >= height => use last input row
- int clamped_row = (row < height) ? row : height - 1;
- int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
- for(col = x; col < x+8; ++col, ++pos) {
- float r, g, b;
- // if col >= width => use pixel from last input column
- int p = base_p + ((col < width) ? col : (width-1))*comp;
-
- r = imageData[p+0];
- g = imageData[p+ofsG];
- b = imageData[p+ofsB];
- YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128;
- UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b;
- VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b;
- }
+static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void *data, int quality) {
+ // Constants that don't pollute global namespace
+ static const unsigned char std_dc_luminance_nrcodes[] = {0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0};
+ static const unsigned char std_dc_luminance_values[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+ static const unsigned char std_ac_luminance_nrcodes[] = {0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d};
+ static const unsigned char std_ac_luminance_values[] = {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71,
+ 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72,
+ 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa};
+ static const unsigned char std_dc_chrominance_nrcodes[] = {0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
+ static const unsigned char std_dc_chrominance_values[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+ static const unsigned char std_ac_chrominance_nrcodes[] = {0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77};
+ static const unsigned char std_ac_chrominance_values[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22,
+ 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
+ 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36,
+ 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
+ 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a,
+ 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
+ 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa};
+ // Huffman tables
+ static const unsigned short YDC_HT[256][2] = {{0, 2}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3},
+ {14, 4}, {30, 5}, {62, 6}, {126, 7}, {254, 8}, {510, 9}};
+ static const unsigned short UVDC_HT[256][2] = {{0, 2}, {1, 2}, {2, 2}, {6, 3}, {14, 4}, {30, 5},
+ {62, 6}, {126, 7}, {254, 8}, {510, 9}, {1022, 10}, {2046, 11}};
+ static const unsigned short YAC_HT[256][2] = {
+ {10, 4}, {0, 2}, {1, 2}, {4, 3}, {11, 4}, {26, 5}, {120, 7}, {248, 8},
+ {1014, 10}, {65410, 16}, {65411, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {12, 4}, {27, 5}, {121, 7}, {502, 9}, {2038, 11}, {65412, 16}, {65413, 16},
+ {65414, 16}, {65415, 16}, {65416, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {28, 5}, {249, 8}, {1015, 10}, {4084, 12}, {65417, 16}, {65418, 16}, {65419, 16},
+ {65420, 16}, {65421, 16}, {65422, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {58, 6}, {503, 9}, {4085, 12}, {65423, 16}, {65424, 16}, {65425, 16}, {65426, 16},
+ {65427, 16}, {65428, 16}, {65429, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {59, 6}, {1016, 10}, {65430, 16}, {65431, 16}, {65432, 16}, {65433, 16}, {65434, 16},
+ {65435, 16}, {65436, 16}, {65437, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {122, 7}, {2039, 11}, {65438, 16}, {65439, 16}, {65440, 16}, {65441, 16}, {65442, 16},
+ {65443, 16}, {65444, 16}, {65445, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {123, 7}, {4086, 12}, {65446, 16}, {65447, 16}, {65448, 16}, {65449, 16}, {65450, 16},
+ {65451, 16}, {65452, 16}, {65453, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {250, 8}, {4087, 12}, {65454, 16}, {65455, 16}, {65456, 16}, {65457, 16}, {65458, 16},
+ {65459, 16}, {65460, 16}, {65461, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {504, 9}, {32704, 15}, {65462, 16}, {65463, 16}, {65464, 16}, {65465, 16}, {65466, 16},
+ {65467, 16}, {65468, 16}, {65469, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {505, 9}, {65470, 16}, {65471, 16}, {65472, 16}, {65473, 16}, {65474, 16}, {65475, 16},
+ {65476, 16}, {65477, 16}, {65478, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {506, 9}, {65479, 16}, {65480, 16}, {65481, 16}, {65482, 16}, {65483, 16}, {65484, 16},
+ {65485, 16}, {65486, 16}, {65487, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {1017, 10}, {65488, 16}, {65489, 16}, {65490, 16}, {65491, 16}, {65492, 16}, {65493, 16},
+ {65494, 16}, {65495, 16}, {65496, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {1018, 10}, {65497, 16}, {65498, 16}, {65499, 16}, {65500, 16}, {65501, 16}, {65502, 16},
+ {65503, 16}, {65504, 16}, {65505, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {2040, 11}, {65506, 16}, {65507, 16}, {65508, 16}, {65509, 16}, {65510, 16}, {65511, 16},
+ {65512, 16}, {65513, 16}, {65514, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {65515, 16}, {65516, 16}, {65517, 16}, {65518, 16}, {65519, 16}, {65520, 16}, {65521, 16},
+ {65522, 16}, {65523, 16}, {65524, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {2041, 11}, {65525, 16}, {65526, 16}, {65527, 16}, {65528, 16}, {65529, 16}, {65530, 16}, {65531, 16},
+ {65532, 16}, {65533, 16}, {65534, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}};
+ static const unsigned short UVAC_HT[256][2] = {
+ {0, 2}, {1, 2}, {4, 3}, {10, 4}, {24, 5}, {25, 5}, {56, 6}, {120, 7},
+ {500, 9}, {1014, 10}, {4084, 12}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {11, 4}, {57, 6}, {246, 8}, {501, 9}, {2038, 11}, {4085, 12}, {65416, 16},
+ {65417, 16}, {65418, 16}, {65419, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {26, 5}, {247, 8}, {1015, 10}, {4086, 12}, {32706, 15}, {65420, 16}, {65421, 16},
+ {65422, 16}, {65423, 16}, {65424, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {27, 5}, {248, 8}, {1016, 10}, {4087, 12}, {65425, 16}, {65426, 16}, {65427, 16},
+ {65428, 16}, {65429, 16}, {65430, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {58, 6}, {502, 9}, {65431, 16}, {65432, 16}, {65433, 16}, {65434, 16}, {65435, 16},
+ {65436, 16}, {65437, 16}, {65438, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {59, 6}, {1017, 10}, {65439, 16}, {65440, 16}, {65441, 16}, {65442, 16}, {65443, 16},
+ {65444, 16}, {65445, 16}, {65446, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {121, 7}, {2039, 11}, {65447, 16}, {65448, 16}, {65449, 16}, {65450, 16}, {65451, 16},
+ {65452, 16}, {65453, 16}, {65454, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {122, 7}, {2040, 11}, {65455, 16}, {65456, 16}, {65457, 16}, {65458, 16}, {65459, 16},
+ {65460, 16}, {65461, 16}, {65462, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {249, 8}, {65463, 16}, {65464, 16}, {65465, 16}, {65466, 16}, {65467, 16}, {65468, 16},
+ {65469, 16}, {65470, 16}, {65471, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {503, 9}, {65472, 16}, {65473, 16}, {65474, 16}, {65475, 16}, {65476, 16}, {65477, 16},
+ {65478, 16}, {65479, 16}, {65480, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {504, 9}, {65481, 16}, {65482, 16}, {65483, 16}, {65484, 16}, {65485, 16}, {65486, 16},
+ {65487, 16}, {65488, 16}, {65489, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {505, 9}, {65490, 16}, {65491, 16}, {65492, 16}, {65493, 16}, {65494, 16}, {65495, 16},
+ {65496, 16}, {65497, 16}, {65498, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {506, 9}, {65499, 16}, {65500, 16}, {65501, 16}, {65502, 16}, {65503, 16}, {65504, 16},
+ {65505, 16}, {65506, 16}, {65507, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {2041, 11}, {65508, 16}, {65509, 16}, {65510, 16}, {65511, 16}, {65512, 16}, {65513, 16},
+ {65514, 16}, {65515, 16}, {65516, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {0, 0}, {16352, 14}, {65517, 16}, {65518, 16}, {65519, 16}, {65520, 16}, {65521, 16}, {65522, 16},
+ {65523, 16}, {65524, 16}, {65525, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ {1018, 10}, {32707, 15}, {65526, 16}, {65527, 16}, {65528, 16}, {65529, 16}, {65530, 16}, {65531, 16},
+ {65532, 16}, {65533, 16}, {65534, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}};
+ static const int YQT[] = {16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55,
+ 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62,
+ 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92,
+ 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99};
+ static const int UVQT[] = {17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99,
+ 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99};
+ static const float aasf[] = {1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f,
+ 1.175875602f * 2.828427125f, 1.0f * 2.828427125f, 0.785694958f * 2.828427125f,
+ 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f};
+
+ int row, col, i, k;
+ float fdtbl_Y[64], fdtbl_UV[64];
+ unsigned char YTable[64], UVTable[64];
+
+ if (!data || !width || !height || comp > 4 || comp < 1) {
+ return 0;
+ }
+
+ quality = quality ? quality : 90;
+ quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
+ quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
+
+ for (i = 0; i < 64; ++i) {
+ int uvti, yti = (YQT[i] * quality + 50) / 100;
+ YTable[stbiw__jpg_ZigZag[i]] = (unsigned char)(yti < 1 ? 1 : yti > 255 ? 255 : yti);
+ uvti = (UVQT[i] * quality + 50) / 100;
+ UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char)(uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
+ }
+
+ for (row = 0, k = 0; row < 8; ++row) {
+ for (col = 0; col < 8; ++col, ++k) {
+ fdtbl_Y[k] = 1 / (YTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
+ fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
+ }
+ }
+
+ // Write Headers
+ {
+ static const unsigned char head0[] = {0xFF, 0xD8, 0xFF, 0xE0, 0, 0x10, 'J', 'F', 'I', 'F', 0, 1, 1,
+ 0, 0, 1, 0, 1, 0, 0, 0xFF, 0xDB, 0, 0x84, 0};
+ static const unsigned char head2[] = {0xFF, 0xDA, 0, 0xC, 3, 1, 0, 2, 0x11, 3, 0x11, 0, 0x3F, 0};
+ const unsigned char head1[] = {0xFF,
+ 0xC0,
+ 0,
+ 0x11,
+ 8,
+ (unsigned char)(height >> 8),
+ STBIW_UCHAR(height),
+ (unsigned char)(width >> 8),
+ STBIW_UCHAR(width),
+ 3,
+ 1,
+ 0x11,
+ 0,
+ 2,
+ 0x11,
+ 1,
+ 3,
+ 0x11,
+ 1,
+ 0xFF,
+ 0xC4,
+ 0x01,
+ 0xA2,
+ 0};
+ s->func(s->context, (void *)head0, sizeof(head0));
+ s->func(s->context, (void *)YTable, sizeof(YTable));
+ stbiw__putc(s, 1);
+ s->func(s->context, UVTable, sizeof(UVTable));
+ s->func(s->context, (void *)head1, sizeof(head1));
+ s->func(s->context, (void *)(std_dc_luminance_nrcodes + 1), sizeof(std_dc_luminance_nrcodes) - 1);
+ s->func(s->context, (void *)std_dc_luminance_values, sizeof(std_dc_luminance_values));
+ stbiw__putc(s, 0x10); // HTYACinfo
+ s->func(s->context, (void *)(std_ac_luminance_nrcodes + 1), sizeof(std_ac_luminance_nrcodes) - 1);
+ s->func(s->context, (void *)std_ac_luminance_values, sizeof(std_ac_luminance_values));
+ stbiw__putc(s, 1); // HTUDCinfo
+ s->func(s->context, (void *)(std_dc_chrominance_nrcodes + 1), sizeof(std_dc_chrominance_nrcodes) - 1);
+ s->func(s->context, (void *)std_dc_chrominance_values, sizeof(std_dc_chrominance_values));
+ stbiw__putc(s, 0x11); // HTUACinfo
+ s->func(s->context, (void *)(std_ac_chrominance_nrcodes + 1), sizeof(std_ac_chrominance_nrcodes) - 1);
+ s->func(s->context, (void *)std_ac_chrominance_values, sizeof(std_ac_chrominance_values));
+ s->func(s->context, (void *)head2, sizeof(head2));
+ }
+
+ // Encode 8x8 macroblocks
+ {
+ static const unsigned short fillBits[] = {0x7F, 7};
+ const unsigned char *imageData = (const unsigned char *)data;
+ int DCY = 0, DCU = 0, DCV = 0;
+ int bitBuf = 0, bitCnt = 0;
+ // comp == 2 is grey+alpha (alpha is ignored)
+ int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
+ int x, y, pos;
+ for (y = 0; y < height; y += 8) {
+ for (x = 0; x < width; x += 8) {
+ float YDU[64], UDU[64], VDU[64];
+ for (row = y, pos = 0; row < y + 8; ++row) {
+ // row >= height => use last input row
+ int clamped_row = (row < height) ? row : height - 1;
+ int base_p =
+ (stbi__flip_vertically_on_write ? (height - 1 - clamped_row) : clamped_row) * width * comp;
+ for (col = x; col < x + 8; ++col, ++pos) {
+ float r, g, b;
+ // if col >= width => use pixel from last input column
+ int p = base_p + ((col < width) ? col : (width - 1)) * comp;
+
+ r = imageData[p + 0];
+ g = imageData[p + ofsG];
+ b = imageData[p + ofsB];
+ YDU[pos] = +0.29900f * r + 0.58700f * g + 0.11400f * b - 128;
+ UDU[pos] = -0.16874f * r - 0.33126f * g + 0.50000f * b;
+ VDU[pos] = +0.50000f * r - 0.41869f * g - 0.08131f * b;
+ }
+ }
+
+ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
+ DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
+ DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
}
+ }
- DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
- DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
- DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
- }
- }
+ // Do the bit alignment of the EOI marker
+ stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
+ }
- // Do the bit alignment of the EOI marker
- stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
- }
+ // EOI
+ stbiw__putc(s, 0xFF);
+ stbiw__putc(s, 0xD9);
- // EOI
- stbiw__putc(s, 0xFF);
- stbiw__putc(s, 0xD9);
-
- return 1;
+ return 1;
}
-STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
-{
- stbi__write_context s;
- stbi__start_write_callbacks(&s, func, context);
- return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
+STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data,
+ int quality) {
+ stbi__write_context s;
+ stbi__start_write_callbacks(&s, func, context);
+ return stbi_write_jpg_core(&s, x, y, comp, (void *)data, quality);
}
-
#ifndef STBI_WRITE_NO_STDIO
-STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
-{
- stbi__write_context s;
- if (stbi__start_write_file(&s,filename)) {
- int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
- stbi__end_write_file(&s);
- return r;
- } else
- return 0;
+STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) {
+ stbi__write_context s;
+ if (stbi__start_write_file(&s, filename)) {
+ int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
+ stbi__end_write_file(&s);
+ return r;
+ } else
+ return 0;
}
#endif
/* Revision history
1.10 (2019-02-07)
- support utf8 filenames in Windows; fix warnings and platform ifdefs
+ support utf8 filenames in Windows; fix warnings and platform ifdefs
1.09 (2018-02-11)
fix typo in zlib quality API, improve STB_I_W_STATIC in C++
1.08 (2018-01-29)
add HDR output
fix monochrome BMP
0.95 (2014-08-17)
- add monochrome TGA output
+ add monochrome TGA output
0.94 (2014-05-31)
rename private functions to avoid conflicts with stb_image.h
0.93 (2014-05-27)
------------------------------------------------------------------------------
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
+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
+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
+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,
+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
+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
+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.
------------------------------------------------------------------------------
*/
// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless.
// See "tests/truetype_demo_win32.c" for a complete version.
#if 0
-#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
+#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
#include "stb_truetype.h"
unsigned char ttf_buffer[1<<20];
//
#if 0
#include <stdio.h>
-#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
+#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
#include "stb_truetype.h"
char ttf_buffer[1<<25];
}
#endif
-
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
////
//// 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 <math.h>
- #define STBTT_ifloor(x) ((int) floor(x))
- #define STBTT_iceil(x) ((int) ceil(x))
- #endif
-
- #ifndef STBTT_sqrt
- #include <math.h>
- #define STBTT_sqrt(x) sqrt(x)
- #define STBTT_pow(x,y) pow(x,y)
- #endif
-
- #ifndef STBTT_fmod
- #include <math.h>
- #define STBTT_fmod(x,y) fmod(x,y)
- #endif
-
- #ifndef STBTT_cos
- #include <math.h>
- #define STBTT_cos(x) cos(x)
- #define STBTT_acos(x) acos(x)
- #endif
-
- #ifndef STBTT_fabs
- #include <math.h>
- #define STBTT_fabs(x) fabs(x)
- #endif
-
- // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
- #ifndef STBTT_malloc
- #include <stdlib.h>
- #define STBTT_malloc(x,u) ((void)(u),malloc(x))
- #define STBTT_free(x,u) ((void)(u),free(x))
- #endif
-
- #ifndef STBTT_assert
- #include <assert.h>
- #define STBTT_assert(x) assert(x)
- #endif
-
- #ifndef STBTT_strlen
- #include <string.h>
- #define STBTT_strlen(x) strlen(x)
- #endif
-
- #ifndef STBTT_memcpy
- #include <string.h>
- #define STBTT_memcpy memcpy
- #define STBTT_memset memset
- #endif
+// #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 <math.h>
+#define STBTT_ifloor(x) ((int)floor(x))
+#define STBTT_iceil(x) ((int)ceil(x))
+#endif
+
+#ifndef STBTT_sqrt
+#include <math.h>
+#define STBTT_sqrt(x) sqrt(x)
+#define STBTT_pow(x, y) pow(x, y)
+#endif
+
+#ifndef STBTT_fmod
+#include <math.h>
+#define STBTT_fmod(x, y) fmod(x, y)
+#endif
+
+#ifndef STBTT_cos
+#include <math.h>
+#define STBTT_cos(x) cos(x)
+#define STBTT_acos(x) acos(x)
+#endif
+
+#ifndef STBTT_fabs
+#include <math.h>
+#define STBTT_fabs(x) fabs(x)
+#endif
+
+// #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
+#ifndef STBTT_malloc
+#include <stdlib.h>
+#define STBTT_malloc(x, u) ((void)(u), malloc(x))
+#define STBTT_free(x, u) ((void)(u), free(x))
+#endif
+
+#ifndef STBTT_assert
+#include <assert.h>
+#define STBTT_assert(x) assert(x)
+#endif
+
+#ifndef STBTT_strlen
+#include <string.h>
+#define STBTT_strlen(x) strlen(x)
+#endif
+
+#ifndef STBTT_memcpy
+#include <string.h>
+#define STBTT_memcpy memcpy
+#define STBTT_memset memset
+#endif
#endif
///////////////////////////////////////////////////////////////////////////////
#endif
// private structure
-typedef struct
-{
- unsigned char *data;
- int cursor;
- int size;
+typedef struct {
+ unsigned char *data;
+ int cursor;
+ int size;
} stbtt__buf;
//////////////////////////////////////////////////////////////////////////////
// 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;
+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
+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
+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
+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.
//
//
// 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);
+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;
+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;
+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);
+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
//
// Returns 0 on failure, 1 on success.
-STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc);
+STBTT_DEF void stbtt_PackEnd(stbtt_pack_context *spc);
// Cleans up the packing context and frees all memory.
-#define STBTT_POINT_SIZE(x) (-(x))
+#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);
+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
// ..., 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
+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);
+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
// 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 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 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);
+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
// 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;
+ 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;
};
//////////////////////////////////////////////////////////////////////////////
// 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
- int fontstart; // offset of start of font
-
- int numGlyphs; // number of glyphs, needed for range checking
-
- int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // 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
-
- 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
+struct stbtt_fontinfo {
+ void *userdata;
+ unsigned char *data; // pointer to .ttf file
+ int fontstart; // offset of start of font
+
+ int numGlyphs; // number of glyphs, needed for range checking
+
+ int loca, head, glyf, hhea, hmtx, kern, gpos, svg; // 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
+
+ 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);
// need to do anything special to free it, because the contents are pure
// value data with no additional data structures. Returns 0 on failure.
-
//////////////////////////////////////////////////////////////////////////////
//
// CHARACTER TO GLYPH-INDEX CONVERSIOn
// codepoint-based functions.
// Returns 0 if the character codepoint is not defined in the font.
-
//////////////////////////////////////////////////////////////////////////////
//
// CHARACTER PROPERTIES
// 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);
+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).
//
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);
+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);
+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 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);
// 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;
+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);
+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)
//
#ifndef STBTT_vmove // you can predefine these to use different values (but why?)
- enum {
- STBTT_vmove=1,
- STBTT_vline,
- STBTT_vcurve,
- STBTT_vcubic
- };
+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;
+#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);
// frees the data allocated above
STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
-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);
+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.
STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
// frees the bitmap allocated below
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y,
+ int codepoint, int *width, int *height, int *xoff, int *yoff);
// allocates a large-enough single-channel 8bpp bitmap and renders the
// specified character/glyph at the specified scale into it, with
// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
//
// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y,
+ float shift_x, float shift_y, int codepoint, int *width,
+ int *height, int *xoff, int *yoff);
// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
// shift for the character
-STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
+STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h,
+ int out_stride, float scale_x, float scale_y, int codepoint);
// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
// width and height and positioning info for it first.
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(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 codepoint);
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(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 codepoint);
// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
// shift for the character
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(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 codepoint);
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(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 codepoint);
// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering
// is performed (see stbtt_PackSetOversampling)
-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_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);
+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_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
-STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
-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);
-
+STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph,
+ int *width, int *height, int *xoff, int *yoff);
+STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y,
+ float shift_x, float shift_y, int glyph, int *width, int *height,
+ int *xoff, int *yoff);
+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;
+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
+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
//////////////////////////////////////////////////////////////////////////////
//
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);
+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),
+// 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)
+// 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
// 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...
// 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
+#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);
+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.
//
// 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
#ifdef STB_TRUETYPE_IMPLEMENTATION
#ifndef STBTT_MAX_OVERSAMPLE
-#define STBTT_MAX_OVERSAMPLE 8
+#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];
+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)
+#define STBTT__NOTUSED(v) (void)(v)
#else
-#define STBTT__NOTUSED(v) (void)sizeof(v)
+#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_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 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_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 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_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;
+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)
+#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__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__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 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);
+ 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);
}
//////////////////////////////////////////////////////////////////////////
// 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(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
-static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
-static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
-static stbtt_int32 ttLONG(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;
+#define ttBYTE(p) (*(stbtt_uint8 *)(p))
+#define ttCHAR(p) (*(stbtt_int8 *)(p))
+#define ttFixed(p) ttLONG(p)
+
+static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0] * 256 + p[1]; }
+static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0] * 256 + p[1]; }
+static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; }
+static stbtt_int32 ttLONG(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 fontstart, const char *tag)
-{
- stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
- stbtt_uint32 tabledir = fontstart + 12;
- stbtt_int32 i;
- for (i=0; i < num_tables; ++i) {
- stbtt_uint32 loc = tabledir + 16*i;
- if (stbtt_tag(data+loc+0, tag))
- return ttULONG(data+loc+8);
- }
- 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);
+static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) {
+ stbtt_int32 num_tables = ttUSHORT(data + fontstart + 4);
+ stbtt_uint32 tabledir = fontstart + 12;
+ stbtt_int32 i;
+ for (i = 0; i < num_tables; ++i) {
+ stbtt_uint32 loc = tabledir + 16 * i;
+ if (stbtt_tag(data + loc + 0, tag))
+ return ttULONG(data + loc + 8);
+ }
+ 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);
}
// since most people won't use this, find this table the first time it's needed
-static int stbtt__get_svg(stbtt_fontinfo *info)
-{
- stbtt_uint32 t;
- if (info->svg < 0) {
- t = stbtt__find_table(info->data, info->fontstart, "SVG ");
- if (t) {
- stbtt_uint32 offset = ttULONG(info->data + t + 2);
- info->svg = t + offset;
- } else {
- info->svg = 0;
- }
- }
- return info->svg;
-}
-
-static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
-{
- stbtt_uint32 cmap, t;
- stbtt_int32 i,numTables;
-
- info->data = data;
- info->fontstart = fontstart;
- info->cff = stbtt__new_buf(NULL, 0);
-
- cmap = stbtt__find_table(data, fontstart, "cmap"); // required
- info->loca = stbtt__find_table(data, fontstart, "loca"); // required
- info->head = stbtt__find_table(data, fontstart, "head"); // required
- info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
- info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
- info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
- info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
- info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
-
- 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, 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, 512*1024*1024);
- 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);
- }
+static int stbtt__get_svg(stbtt_fontinfo *info) {
+ stbtt_uint32 t;
+ if (info->svg < 0) {
+ t = stbtt__find_table(info->data, info->fontstart, "SVG ");
+ if (t) {
+ stbtt_uint32 offset = ttULONG(info->data + t + 2);
+ info->svg = t + offset;
+ } else {
+ info->svg = 0;
+ }
+ }
+ return info->svg;
+}
+
+static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) {
+ stbtt_uint32 cmap, t;
+ stbtt_int32 i, numTables;
+
+ info->data = data;
+ info->fontstart = fontstart;
+ info->cff = stbtt__new_buf(NULL, 0);
+
+ cmap = stbtt__find_table(data, fontstart, "cmap"); // required
+ info->loca = stbtt__find_table(data, fontstart, "loca"); // required
+ info->head = stbtt__find_table(data, fontstart, "head"); // required
+ info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
+ info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
+ info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
+ info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
+ info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
+
+ 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, fontstart, "CFF ");
+ if (!cff)
+ return 0;
- stbtt__buf_seek(&b, charstrings);
- info->charstrings = stbtt__cff_get_index(&b);
- }
+ 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, 512 * 1024 * 1024);
+ 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;
- t = stbtt__find_table(data, 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;
+ 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, 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);
+ info->index_map = cmap + ttULONG(data + encoding_record + 4);
break;
- }
- }
- if (info->index_map == 0)
- return 0;
-
- info->indexToLocFormat = ttUSHORT(data+info->head + 50);
- 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, last;
- stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
-
- start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
- last = ttUSHORT(data + endCount + 2*item);
- if (unicode_codepoint < start || unicode_codepoint > last)
+ }
+ }
+ if (info->index_map == 0)
+ return 0;
+
+ info->indexToLocFormat = ttUSHORT(data + info->head + 50);
+ 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;
- 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;
+ // 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, last;
+ stbtt_uint16 item = (stbtt_uint16)((search - endCount) >> 1);
+
+ start = ttUSHORT(data + index_map + 14 + segcount * 2 + 2 + 2 * item);
+ last = ttUSHORT(data + endCount + 2 * item);
+ if (unicode_codepoint < start || unicode_codepoint > last)
+ 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)
-{
- return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
+STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) {
+ return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
}
-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 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;
+static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) {
+ int g1, g2;
- STBTT_assert(!info->cff.size);
+ 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 (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);
- }
+ 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
+ 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 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__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
-{
- 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;
-
- 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;
- }
+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;
- // 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;
- }
+ 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 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__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) {
+ 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;
+
+ 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;
- // 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
- }
+ 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 {
- sx = x;
- sy = y;
+ if (!(flags & 16)) {
+ x = x + (stbtt_int16)(points[0] * 256 + points[1]);
+ points += 2;
+ }
}
- 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;
+ 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 (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;
+ if (!(flags & 32)) {
+ y = y + (stbtt_int16)(points[0] * 256 + points[1]);
+ points += 2;
+ }
}
- }
- }
- 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;
- num_vertices = 0;
- vertices = 0;
- while (more) {
- stbtt_uint16 flags, gidx;
- int comp_num_verts = 0, i;
- stbtt_vertex *comp_verts = 0, *tmp = 0;
- float mtx[6] = {1,0,0,1,0,0}, m, n;
-
- flags = ttSHORT(comp); comp+=2;
- gidx = ttSHORT(comp); comp+=2;
-
- if (flags & 2) { // XY values
- if (flags & 1) { // shorts
- mtx[4] = ttSHORT(comp); comp+=2;
- mtx[5] = ttSHORT(comp); comp+=2;
+ vertices[off + i].y = (stbtt_int16)y;
+ }
+
+ // 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 {
- mtx[4] = ttCHAR(comp); comp+=1;
- mtx[5] = ttCHAR(comp); comp+=1;
+ 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;
+ }
}
- }
- else {
- // @TODO handle matching point
- STBTT_assert(0);
- }
- 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]);
-
- // Get indexed glyph.
- comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
- 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 + mtx[4]));
- v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
- x=v->cx; y=v->cy;
- v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
- v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
+ }
+ 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;
+ num_vertices = 0;
+ vertices = 0;
+ while (more) {
+ stbtt_uint16 flags, gidx;
+ int comp_num_verts = 0, i;
+ stbtt_vertex *comp_verts = 0, *tmp = 0;
+ float mtx[6] = {1, 0, 0, 1, 0, 0}, m, n;
+
+ flags = ttSHORT(comp);
+ comp += 2;
+ gidx = ttSHORT(comp);
+ comp += 2;
+
+ if (flags & 2) { // XY values
+ if (flags & 1) { // shorts
+ mtx[4] = ttSHORT(comp);
+ comp += 2;
+ mtx[5] = ttSHORT(comp);
+ comp += 2;
+ } else {
+ mtx[4] = ttCHAR(comp);
+ comp += 1;
+ mtx[5] = ttCHAR(comp);
+ comp += 1;
+ }
+ } else {
+ // @TODO handle matching point
+ STBTT_assert(0);
}
- // 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 (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;
}
- if (num_vertices > 0 && vertices) 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;
+ // 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]);
+
+ // Get indexed glyph.
+ comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
+ 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 + mtx[4]));
+ v->y = (stbtt_vertex_type)(n * (mtx[1] * x + mtx[3] * y + mtx[5]));
+ x = v->cx;
+ y = v->cy;
+ v->cx = (stbtt_vertex_type)(m * (mtx[0] * x + mtx[2] * y + mtx[4]));
+ v->cy = (stbtt_vertex_type)(n * (mtx[1] * x + mtx[3] * y + mtx[5]));
+ }
+ // 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 && vertices)
+ 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);
+#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 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 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;
-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);
-}
+#define STBTT__CSERR(s) (0)
-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;
+ // 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;
- }
- 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);
+ case 0x01: // hstem
+ case 0x03: // vstem
+ case 0x12: // hstemhm
+ case 0x17: // vstemhm
+ maskbits += (sp / 2);
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);
+ 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 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));
+ 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;
- 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);
+ // 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;
- default:
- return STBTT__CSERR("unimplemented");
- }
- } break;
-
- default:
- if (b0 != 255 && b0 != 28 && b0 < 32)
- 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");
+ 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;
-#undef STBTT__CSERR
-}
+ 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;
-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;
-}
+ 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;
-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;
-}
+ 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;
-STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
-{
- if (!info->cff.size)
- return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
- else
- return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
-}
+ 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;
-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));
- }
-}
+ 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;
-STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
-{
- stbtt_uint8 *data = info->data + info->kern;
+ case 0x0B: // return
+ if (subr_stack_height <= 0)
+ return STBTT__CSERR("return outside subr");
+ b = subr_stack[--subr_stack_height];
+ clear_stack = 0;
+ break;
- // 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;
+ 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;
- return ttUSHORT(data+10);
-}
+ default:
+ return STBTT__CSERR("unimplemented");
+ }
+ } break;
-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));
- }
+ default:
+ if (b0 != 255 && b0 != 28 && b0 < 32)
+ return STBTT__CSERR("reserved operator");
- return length;
-}
+ // 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");
-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;
+#undef STBTT__CSERR
}
-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) {
+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) {
+ if (!info->cff.size)
+ return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
+ else
+ 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;
+ m = (l + r) >> 1;
glyphID = ttUSHORT(glyphArray + 2 * m);
- straw = glyphID;
+ straw = glyphID;
if (needle < straw)
- r = m - 1;
+ r = m - 1;
else if (needle > straw)
- l = m + 1;
+ l = m + 1;
else {
- return m;
+ 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) {
+ }
+ 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;
+ m = (l + r) >> 1;
rangeRecord = rangeArray + 6 * m;
- strawStart = ttUSHORT(rangeRecord);
- strawEnd = ttUSHORT(rangeRecord + 2);
+ strawStart = ttUSHORT(rangeRecord);
+ strawEnd = ttUSHORT(rangeRecord + 2);
if (needle < strawStart)
- r = m - 1;
+ r = m - 1;
else if (needle > strawEnd)
- l = m + 1;
+ l = m + 1;
else {
- stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
- return startCoverageIndex + glyph - strawStart;
+ stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
+ return startCoverageIndex + glyph - strawStart;
}
- }
- break;
- }
+ }
+ break;
+ }
- default: return -1; // unsupported
- }
+ default:
+ return -1; // unsupported
+ }
- return -1;
+ 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)
+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));
- break;
- }
+ break;
+ }
- case 2: {
- stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
- stbtt_uint8 *classRangeRecords = classDefTable + 4;
+ 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) {
+ // 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;
+ m = (l + r) >> 1;
classRangeRecord = classRangeRecords + 6 * m;
- strawStart = ttUSHORT(classRangeRecord);
- strawEnd = ttUSHORT(classRangeRecord + 2);
+ strawStart = ttUSHORT(classRangeRecord);
+ strawEnd = ttUSHORT(classRangeRecord + 2);
if (needle < strawStart)
- r = m - 1;
+ r = m - 1;
else if (needle > strawEnd)
- l = m + 1;
+ l = m + 1;
else
- return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
- }
- break;
- }
+ return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
+ }
+ break;
+ }
- default:
- return -1; // Unsupported definition type, return an error.
- }
+ default:
+ return -1; // Unsupported definition type, return an error.
+ }
- // "All glyphs not assigned to a class fall into class 0". (OpenType spec)
- return 0;
+ // "All glyphs not assigned to a class fall into class 0". (OpenType spec)
+ return 0;
}
// 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, sti;
-
- 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<lookupCount; ++i) {
- stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
- stbtt_uint8 *lookupTable = lookupList + lookupOffset;
-
- stbtt_uint16 lookupType = ttUSHORT(lookupTable);
- stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
- stbtt_uint8 *subTableOffsets = lookupTable + 6;
- if (lookupType != 2) // Pair Adjustment Positioning Subtable
- continue;
-
- for (sti=0; sti<subTableCount; sti++) {
- stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
- stbtt_uint8 *table = lookupTable + subtableOffset;
- stbtt_uint16 posFormat = ttUSHORT(table);
- stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
- stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
- if (coverageIndex == -1) continue;
-
- switch (posFormat) {
+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, sti;
+
+ 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 < lookupCount; ++i) {
+ stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
+ stbtt_uint8 *lookupTable = lookupList + lookupOffset;
+
+ stbtt_uint16 lookupType = ttUSHORT(lookupTable);
+ stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
+ stbtt_uint8 *subTableOffsets = lookupTable + 6;
+ if (lookupType != 2) // Pair Adjustment Positioning Subtable
+ continue;
+
+ for (sti = 0; sti < subTableCount; sti++) {
+ stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
+ stbtt_uint8 *table = lookupTable + subtableOffset;
+ stbtt_uint16 posFormat = ttUSHORT(table);
+ stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
+ stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
+ if (coverageIndex == -1)
+ continue;
+
+ switch (posFormat) {
case 1: {
- stbtt_int32 l, r, m;
- int straw, needle;
- stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
- stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
- if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
- stbtt_int32 valueRecordPairSizeInBytes = 2;
- stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
- stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
- stbtt_uint8 *pairValueTable = table + pairPosOffset;
- stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
- stbtt_uint8 *pairValueArray = pairValueTable + 2;
-
- if (coverageIndex >= pairSetCount) return 0;
-
- needle=glyph2;
- r=pairValueCount-1;
- l=0;
-
- // Binary search.
- while (l <= r) {
- stbtt_uint16 secondGlyph;
- stbtt_uint8 *pairValue;
- m = (l + r) >> 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;
- }
- }
- } else
- return 0;
- break;
+ stbtt_int32 l, r, m;
+ int straw, needle;
+ stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
+ stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
+ if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
+ stbtt_int32 valueRecordPairSizeInBytes = 2;
+ stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
+ stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
+ stbtt_uint8 *pairValueTable = table + pairPosOffset;
+ stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
+ stbtt_uint8 *pairValueArray = pairValueTable + 2;
+
+ if (coverageIndex >= pairSetCount)
+ return 0;
+
+ needle = glyph2;
+ r = pairValueCount - 1;
+ l = 0;
+
+ // Binary search.
+ while (l <= r) {
+ stbtt_uint16 secondGlyph;
+ stbtt_uint8 *pairValue;
+ m = (l + r) >> 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;
+ }
+ }
+ } else
+ return 0;
+ break;
}
case 2: {
- stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
- stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
- if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
- 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_uint8 *class1Records, *class2Records;
- stbtt_int16 xAdvance;
-
- if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
- if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
-
- class1Records = table + 16;
- class2Records = class1Records + 2 * (glyph1class * class2Count);
- xAdvance = ttSHORT(class2Records + 2 * glyph2class);
- return xAdvance;
- } else
- return 0;
- break;
+ stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
+ stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
+ if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
+ 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_uint8 *class1Records, *class2Records;
+ stbtt_int16 xAdvance;
+
+ if (glyph1class < 0 || glyph1class >= class1Count)
+ return 0; // malformed
+ if (glyph2class < 0 || glyph2class >= class2Count)
+ return 0; // malformed
+
+ class1Records = table + 16;
+ class2Records = class1Records + 2 * (glyph1class * class2Count);
+ xAdvance = ttSHORT(class2Records + 2 * glyph2class);
+ return xAdvance;
+ } else
+ return 0;
+ break;
}
default:
- return 0; // Unsupported position format
- }
- }
- }
+ return 0; // Unsupported position format
+ }
+ }
+ }
- return 0;
+ return 0;
}
-STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
-{
- int xAdvance = 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);
+ if (info->gpos)
+ xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
+ else if (info->kern)
+ xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
- return xAdvance;
+ 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 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_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 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->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 int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent,
+ int *typoLineGap) {
+ int tab = stbtt__find_table(info->data, 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 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_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_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
-{
- int unitsPerEm = ttUSHORT(info->data + info->head + 18);
- return pixels / unitsPerEm;
+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);
-}
+STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) { STBTT_free(v, info->userdata); }
-STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
-{
- int i;
- stbtt_uint8 *data = info->data;
- stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
+STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) {
+ int i;
+ stbtt_uint8 *data = info->data;
+ stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *)info);
- int numEntries = ttUSHORT(svg_doc_list);
- stbtt_uint8 *svg_docs = svg_doc_list + 2;
+ int numEntries = ttUSHORT(svg_doc_list);
+ stbtt_uint8 *svg_docs = svg_doc_list + 2;
- for(i=0; i<numEntries; i++) {
- stbtt_uint8 *svg_doc = svg_docs + (12 * i);
- if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
- return svg_doc;
- }
- return 0;
+ for (i = 0; i < numEntries; i++) {
+ stbtt_uint8 *svg_doc = svg_docs + (12 * i);
+ if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
+ return svg_doc;
+ }
+ return 0;
}
-STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
-{
- stbtt_uint8 *data = info->data;
- stbtt_uint8 *svg_doc;
-
- if (info->svg == 0)
- return 0;
-
- svg_doc = stbtt_FindSVGDoc(info, gl);
- if (svg_doc != NULL) {
- *svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
- return ttULONG(svg_doc + 8);
- } else {
- return 0;
- }
+STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) {
+ stbtt_uint8 *data = info->data;
+ stbtt_uint8 *svg_doc;
+
+ if (info->svg == 0)
+ return 0;
+
+ svg_doc = stbtt_FindSVGDoc(info, gl);
+ if (svg_doc != NULL) {
+ *svg = (char *)data + info->svg + ttULONG(svg_doc + 4);
+ return ttULONG(svg_doc + 8);
+ } else {
+ return 0;
+ }
}
-STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
-{
- return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
+STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) {
+ return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
}
//////////////////////////////////////////////////////////////////////////////
// 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,y1; // =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)?
- if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
- if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
- if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
- if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
- }
-}
-
-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);
+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, y1; // =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)?
+ if (ix0)
+ *ix0 = STBTT_ifloor(x0 * scale_x + shift_x);
+ if (iy0)
+ *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
+ if (ix1)
+ *ix1 = STBTT_iceil(x1 * scale_x + shift_x);
+ if (iy1)
+ *iy1 = STBTT_iceil(-y0 * scale_y + shift_y);
+ }
+}
+
+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;
+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;
+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;
- }
+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;
+ 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
+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;
+#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;
+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"
// 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;
- }
+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
+ }
+
+ 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;
+
+ // 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;
}
- 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;
- }
- }
+
+ // 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;
}
- ++e;
- }
- // now process all active edges in XOR fashion
- if (active)
- stbtt__fill_active_edges(scanline, result->w, active, max_weight);
+ // 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;
- }
+ ++y;
+ }
+ STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
+ ++j;
+ }
- stbtt__hheap_cleanup(&hh, userdata);
+ stbtt__hheap_cleanup(&hh, userdata);
- if (scanline != scanline_data)
- STBTT_free(scanline, 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 float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
-{
- STBTT_assert(top_width >= 0);
- STBTT_assert(bottom_width >= 0);
- return (top_width + bottom_width) / 2.0f * height;
-}
-
-static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
-{
- return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
-}
-
-static float stbtt__sized_triangle_area(float height, float width)
-{
- return height * width / 2;
-}
-
-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);
+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 float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) {
+ STBTT_assert(top_width >= 0);
+ STBTT_assert(bottom_width >= 0);
+ return (top_width + bottom_width) / 2.0f * height;
+}
+
+static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) {
+ return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
+}
+
+static float stbtt__sized_triangle_area(float height, float width) { return height * width / 2; }
+
+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 {
- stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
+ x_top = x0;
+ sy0 = y_top;
}
- }
- } 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) * e->direction;
- STBTT_assert(x >= 0 && x < len);
- scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
- scanline_fill[x] += height; // everything right of this pixel is filled
+ if (e->ey < y_bottom) {
+ x_bottom = x0 + dx * (e->ey - y_top);
+ sy1 = e->ey;
} else {
- int x,x1,x2;
- float y_crossing, y_final, 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;
- }
- STBTT_assert(dy >= 0);
- STBTT_assert(dx >= 0);
-
- x1 = (int) x_top;
- x2 = (int) x_bottom;
- // compute intersection with y axis at x1+1
- y_crossing = y_top + dy * (x1+1 - x0);
-
- // compute intersection with y axis at x2
- y_final = y_top + dy * (x2 - x0);
-
- // x1 x_top x2 x_bottom
- // y_top +------|-----+------------+------------+--------|---+------------+
- // | | | | | |
- // | | | | | |
- // sy0 | Txxxxx|............|............|............|............|
- // y_crossing | *xxxxx.......|............|............|............|
- // | | xxxxx..|............|............|............|
- // | | /- xx*xxxx........|............|............|
- // | | dy < | xxxxxx..|............|............|
- // y_final | | \- | xx*xxx.........|............|
- // sy1 | | | | xxxxxB...|............|
- // | | | | | |
- // | | | | | |
- // y_bottom +------------+------------+------------+------------+------------+
- //
- // goal is to measure the area covered by '.' in each pixel
-
- // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
- // @TODO: maybe test against sy1 rather than y_bottom?
- if (y_crossing > y_bottom)
- y_crossing = y_bottom;
-
- sign = e->direction;
-
- // area of the rectangle covered from sy0..y_crossing
- area = sign * (y_crossing-sy0);
-
- // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
- scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
-
- // check if final y_crossing is blown up; no test case for this
- if (y_final > y_bottom) {
- y_final = y_bottom;
- dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom
- }
-
- // in second pixel, area covered by line segment found in first pixel
- // is always a rectangle 1 wide * the height of that line segment; this
- // is exactly what the variable 'area' stores. it also gets a contribution
- // from the line segment within it. the THIRD pixel will get the first
- // pixel's rectangle contribution, the second pixel's rectangle contribution,
- // and its own contribution. the 'own contribution' is the same in every pixel except
- // the leftmost and rightmost, a trapezoid that slides down in each pixel.
- // the second pixel's contribution to the third pixel will be the
- // rectangle 1 wide times the height change in the second pixel, which is dy.
-
- step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
- // which multiplied by 1-pixel-width is how much pixel area changes for each step in x
- // so the area advances by 'step' every time
-
- for (x = x1+1; x < x2; ++x) {
- scanline[x] += area + step/2; // area of trapezoid is 1*step/2
- area += step;
- }
- STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down
- STBTT_assert(sy1 > y_final-0.01f);
-
- // area covered in the last pixel is the rectangle from all the pixels to the left,
- // plus the trapezoid filled by the line segment in this pixel all the way to the right edge
- scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
-
- // the rest of the line is filled based on the total height of the line segment in this pixel
- scanline_fill[x2] += sign * (sy1-sy0);
+ x_bottom = xb;
+ sy1 = y_bottom;
}
- } 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
- // note though that this does happen some of the time because
- // x_top and x_bottom can be extrapolated at the top & bottom of
- // the shape and actually lie outside the bounding box
- 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);
- }
+
+ 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) * e->direction;
+ STBTT_assert(x >= 0 && x < len);
+ scanline[x] += stbtt__position_trapezoid_area(height, x_top, x + 1.0f, x_bottom, x + 1.0f);
+ scanline_fill[x] += height; // everything right of this pixel is filled
+ } else {
+ int x, x1, x2;
+ float y_crossing, y_final, 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;
+ }
+ STBTT_assert(dy >= 0);
+ STBTT_assert(dx >= 0);
+
+ x1 = (int)x_top;
+ x2 = (int)x_bottom;
+ // compute intersection with y axis at x1+1
+ y_crossing = y_top + dy * (x1 + 1 - x0);
+
+ // compute intersection with y axis at x2
+ y_final = y_top + dy * (x2 - x0);
+
+ // x1 x_top x2 x_bottom
+ // y_top +------|-----+------------+------------+--------|---+------------+
+ // | | | | | |
+ // | | | | | |
+ // sy0 | Txxxxx|............|............|............|............|
+ // y_crossing | *xxxxx.......|............|............|............|
+ // | | xxxxx..|............|............|............|
+ // | | /- xx*xxxx........|............|............|
+ // | | dy < | xxxxxx..|............|............|
+ // y_final | | \- | xx*xxx.........|............|
+ // sy1 | | | | xxxxxB...|............|
+ // | | | | | |
+ // | | | | | |
+ // y_bottom +------------+------------+------------+------------+------------+
+ //
+ // goal is to measure the area covered by '.' in each pixel
+
+ // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
+ // @TODO: maybe test against sy1 rather than y_bottom?
+ if (y_crossing > y_bottom)
+ y_crossing = y_bottom;
+
+ sign = e->direction;
+
+ // area of the rectangle covered from sy0..y_crossing
+ area = sign * (y_crossing - sy0);
+
+ // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
+ scanline[x1] += stbtt__sized_triangle_area(area, x1 + 1 - x_top);
+
+ // check if final y_crossing is blown up; no test case for this
+ if (y_final > y_bottom) {
+ y_final = y_bottom;
+ dy = (y_final - y_crossing) /
+ (x2 - (x1 + 1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom
+ }
+
+ // in second pixel, area covered by line segment found in first pixel
+ // is always a rectangle 1 wide * the height of that line segment; this
+ // is exactly what the variable 'area' stores. it also gets a contribution
+ // from the line segment within it. the THIRD pixel will get the first
+ // pixel's rectangle contribution, the second pixel's rectangle contribution,
+ // and its own contribution. the 'own contribution' is the same in every pixel except
+ // the leftmost and rightmost, a trapezoid that slides down in each pixel.
+ // the second pixel's contribution to the third pixel will be the
+ // rectangle 1 wide times the height change in the second pixel, which is dy.
+
+ step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
+ // which multiplied by 1-pixel-width is how much pixel area changes for each step in x
+ // so the area advances by 'step' every time
+
+ for (x = x1 + 1; x < x2; ++x) {
+ scanline[x] += area + step / 2; // area of trapezoid is 1*step/2
+ area += step;
+ }
+ STBTT_assert(STBTT_fabs(area) <=
+ 1.01f); // accumulated error from area += step unless we round step down
+ STBTT_assert(sy1 > y_final - 0.01f);
+
+ // area covered in the last pixel is the rectangle from all the pixels to the left,
+ // plus the trapezoid filled by the line segment in this pixel all the way to the right edge
+ scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1 - y_final, (float)x2, x2 + 1.0f,
+ x_bottom, x2 + 1.0f);
+
+ // the rest of the line is filled based on the total height of the line segment in this pixel
+ 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
+ // note though that this does happen some of the time because
+ // x_top and x_bottom can be extrapolated at the top & bottom of
+ // the shape and actually lie outside the bounding box
+ 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;
- }
+ }
+ 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;
+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
}
- }
- ++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
- }
+ }
+
+ // 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;
- }
+ ++y;
+ ++j;
+ }
- stbtt__hheap_cleanup(&hh, userdata);
+ stbtt__hheap_cleanup(&hh, userdata);
- if (scanline != scanline_data)
- STBTT_free(scanline, 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 && mid<n: 0>n => n; 0<n => 0 */
- /* 0<mid && mid>n: 0>n => 0; 0<n => 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;
+#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 && mid<n: 0>n => n; 0<n => 0 */
+ /* 0<mid && mid>n: 0>n => 0; 0<n => 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;
+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;
+ int vsubsample = result->h < 8 ? 15 : 5;
#elif STBTT_RASTERIZER_VERSION == 2
- int vsubsample = 1;
+ int vsubsample = 1;
#else
- #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
+#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;
- }
- }
+ // 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 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);
+ // 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);
+ 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;
+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;
- }
+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) {
+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;
+ // 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;
+ 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;
+ 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;
- }
+ 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;
+ 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_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
-{
- int ix0,iy0,ix1,iy1;
- stbtt__bitmap gbm;
- stbtt_vertex *vertices;
- int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
-
- 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_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_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y,
+ float shift_x, float shift_y, int glyph, int *width, int *height,
+ int *xoff, int *yoff) {
+ int ix0, iy0, ix1, iy1;
+ stbtt__bitmap gbm;
+ stbtt_vertex *vertices;
+ int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
+
+ 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_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
+ stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0, &iy0, &ix1, &iy1);
- // now we get the size
- gbm.w = (ix1 - ix0);
- gbm.h = (iy1 - iy0);
- gbm.pixels = NULL; // in case we error
+ // now we get the size
+ gbm.w = (ix1 - ix0);
+ gbm.h = (iy1 - iy0);
+ gbm.pixels = NULL; // in case we error
- if (width ) *width = gbm.w;
- if (height) *height = gbm.h;
- if (xoff ) *xoff = ix0;
- if (yoff ) *yoff = iy0;
+ if (width)
+ *width = gbm.w;
+ if (height)
+ *height = gbm.h;
+ if (xoff)
+ *xoff = ix0;
+ if (yoff)
+ *yoff = iy0;
- if (gbm.w && gbm.h) {
- gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
- if (gbm.pixels) {
- gbm.stride = gbm.w;
+ if (gbm.w && gbm.h) {
+ gbm.pixels = (unsigned char *)STBTT_malloc(gbm.w * gbm.h, info->userdata);
+ if (gbm.pixels) {
+ gbm.stride = gbm.w;
- 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);
- return gbm.pixels;
+ 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);
+ return gbm.pixels;
}
-STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
-{
- return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
+STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph,
+ int *width, int *height, int *xoff, int *yoff) {
+ return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
}
-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);
- stbtt__bitmap gbm;
+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);
+ 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;
+ 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);
+ 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_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);
+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);
}
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
-{
- return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y,
+ float shift_x, float shift_y, int codepoint, int *width,
+ int *height, int *xoff, int *yoff) {
+ return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info, codepoint),
+ width, height, xoff, yoff);
}
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(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 codepoint)
-{
- stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(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 codepoint) {
+ stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y,
+ oversample_x, oversample_y, sub_x, sub_y,
+ stbtt_FindGlyphIndex(info, codepoint));
}
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(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 codepoint)
-{
- stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(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 codepoint) {
+ stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y,
+ stbtt_FindGlyphIndex(info, codepoint));
}
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
-{
- return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y,
+ int codepoint, int *width, int *height, int *xoff, int *yoff) {
+ return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, codepoint, width, height, xoff, yoff);
}
-STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
-{
- stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
+STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h,
+ int out_stride, float scale_x, float scale_y, int codepoint) {
+ stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f, 0.0f, codepoint);
}
//////////////////////////////////////////////////////////////////////////////
//
// 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;
+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;
}
//////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////////////
-typedef struct
-{
- int width,height;
- int x,y,bottom_y;
+typedef struct {
+ int width, height;
+ int x, y, bottom_y;
} stbrp_context;
-typedef struct
-{
- unsigned char x;
+typedef struct {
+ unsigned char x;
} stbrp_node;
-struct stbrp_rect
-{
- stbrp_coord x,y;
- int id,w,h,was_packed;
+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;
+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
// 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);
+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);
+ 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);
+ 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);
+ 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);
+ 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);
+ }
+
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
- }
+ 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;
- }
+ pixels += 1;
+ }
}
-static float stbtt__oversample_shift(int oversample)
-{
- if (!oversample)
- return 0.0f;
+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);
+ // 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;
- }
- }
+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;
+ 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);
+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_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);
+ 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);
+ *sub_x = stbtt__oversample_shift(prefilter_x);
+ *sub_y = stbtt__oversample_shift(prefilter_y);
}
// 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;
- }
- }
+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
+ }
- // restore original values
- spc->h_oversample = old_h_over;
- spc->v_oversample = old_v_over;
+ ++k;
+ }
+ }
- return return_value;
+ // 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 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;
+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;
+ // 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;
+ 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;
+ 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));
+ info.userdata = spc->user_allocator_context;
+ stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, font_index));
- n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
+ n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
- stbtt_PackFontRangesPackRects(spc, rects, n);
+ stbtt_PackFontRangesPackRects(spc, rects, n);
- return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
+ return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
- STBTT_free(rects, spc->user_allocator_context);
- return return_value;
+ 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 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;
- }
+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;
- q->s0 = b->x0 * ipw;
- q->t0 = b->y0 * iph;
- q->s1 = b->x1 * ipw;
- q->t1 = b->y1 * iph;
+ 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;
+ }
- *xpos += b->xadvance;
+ 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
//
-#define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
-#define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
-
-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)
+#define STBTT_min(a, b) ((a) < (b) ? (a) : (b))
+#define STBTT_max(a, b) ((a) < (b) ? (b) : (a))
+
+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 (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;
-
- // 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[0] = x;
- 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);
+ }
+
+ 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;
+
+ // 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[0] = x;
+ 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;
}
- }
- }
- }
- return winding;
+ }
+ 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);
+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 + a*x^2 + b*x + c = 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 ix0,iy0,ix1,iy1;
- int w,h;
- unsigned char *data;
-
- if (scale == 0) return NULL;
-
- stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
-
- // if empty, return NULL
- if (ix0 == ix1 || iy0 == iy1)
- return NULL;
-
- 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;
- stbtt_vertex *verts;
- int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
- 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;
-
- if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
- float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
-
- float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
- if (dist2 < min_dist*min_dist)
- min_dist = (float) STBTT_sqrt(dist2);
-
- // 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)
- 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] = {0.f,0.f,0.f};
- float px,py,t,it,dist2;
- 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);
- }
- dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
- if (dist2 < min_dist*min_dist)
- min_dist = (float) STBTT_sqrt(dist2);
-
- 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);
+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 ix0, iy0, ix1, iy1;
+ int w, h;
+ unsigned char *data;
+
+ if (scale == 0)
+ return NULL;
+
+ stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f, 0.0f, &ix0, &iy0, &ix1, &iy1);
+
+ // if empty, return NULL
+ if (ix0 == ix1 || iy0 == iy1)
+ return NULL;
+
+ 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;
+ stbtt_vertex *verts;
+ int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
+ 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;
+
+ if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
+ float x1 = verts[i - 1].x * scale_x, y1 = verts[i - 1].y * scale_y;
+
+ float dist, dist2 = (x0 - sx) * (x0 - sx) + (y0 - sy) * (y0 - sy);
if (dist2 < min_dist * min_dist)
- min_dist = (float) STBTT_sqrt(dist2);
- }
- }
- }
+ min_dist = (float)STBTT_sqrt(dist2);
+
+ // 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)
+ 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] = {0.f, 0.f, 0.f};
+ float px, py, t, it, dist2;
+ 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);
+ }
+ dist2 = (x0 - sx) * (x0 - sx) + (y0 - sy) * (y0 - sy);
+ if (dist2 < min_dist * min_dist)
+ min_dist = (float)STBTT_sqrt(dist2);
+
+ 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;
}
- 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_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 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);
-}
+STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) { STBTT_free(bitmap, userdata); }
//////////////////////////////////////////////////////////////////////////////
//
//
// 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);
+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, 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;
- }
+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, 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;
+ // @TODO handle other encodings
+ }
+ }
+ return 0;
}
-static int stbtt__matches(stbtt_uint8 *fc, 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, offset, "head");
- if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
- }
-
- nm = stbtt__find_table(fc, 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;
- }
+static int stbtt__matches(stbtt_uint8 *fc, 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;
- return 0;
-}
-
-static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
-{
- stbtt_int32 i;
- for (i=0;;++i) {
- stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
- if (off < 0) return off;
- if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
- return off;
- }
+ // check italics/bold/underline flags in macStyle...
+ if (flags) {
+ hd = stbtt__find_table(fc, offset, "head");
+ if ((ttUSHORT(fc + hd + 44) & 7) != (flags & 7))
+ return 0;
+ }
+
+ nm = stbtt__find_table(fc, 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, char *name_utf8, stbtt_int32 flags) {
+ stbtt_int32 i;
+ for (i = 0;; ++i) {
+ stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
+ if (off < 0)
+ return off;
+ if (stbtt__matches((stbtt_uint8 *)font_collection, off, (stbtt_uint8 *)name_utf8, flags))
+ return off;
+ }
}
#if defined(__GNUC__) || defined(__clang__)
#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_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_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_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, offset);
+STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) {
+ return stbtt_InitFont_internal(info, (unsigned char *)data, offset);
}
-STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
-{
- return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
+STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) {
+ return stbtt_FindMatchingFont_internal((unsigned char *)fontdata, (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_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) {
+ return stbtt_CompareUTF8toUTF16_bigendian_internal((char *)s1, len1, (char *)s2, len2);
}
#if defined(__GNUC__) || defined(__clang__)
#endif // STB_TRUETYPE_IMPLEMENTATION
-
// FULL VERSION HISTORY
//
// 1.25 (2021-07-11) many fixes
#include "vkvg_internal.h"
typedef struct {
- float x;
- float y;
-}vec2;
+ float x;
+ float y;
+} vec2;
-static const vec2 vec2_unit_x = {1.f,0};
-static const vec2 vec2_unit_y = {0,1.f};
+static const vec2 vec2_unit_x = {1.f, 0};
+static const vec2 vec2_unit_y = {0, 1.f};
typedef struct {
- double x;
- double y;
-}vec2d;
+ double x;
+ double y;
+} vec2d;
/*const vec2d vec2d_unit_x = {1.0,0};
const vec2d vec2d_unit_y = {0,1.0};*/
typedef struct {
- float x;
- float y;
- float z;
-}vec3;
+ float x;
+ float y;
+ float z;
+} vec3;
typedef struct {
- union {
- float x;
- float r;
- float xMin;
- };
- union {
- float y;
- float g;
- float yMin;
- };
- union {
- float z;
- float width;
- float b;
- float xMax;
- };
- union {
- float w;
- float height;
- float a;
- float yMax;
- };
-
-}vec4;
+ union {
+ float x;
+ float r;
+ float xMin;
+ };
+ union {
+ float y;
+ float g;
+ float yMin;
+ };
+ union {
+ float z;
+ float width;
+ float b;
+ float xMax;
+ };
+ union {
+ float w;
+ float height;
+ float a;
+ float yMax;
+ };
+
+} vec4;
typedef struct {
- uint16_t x;
- uint16_t y;
- uint16_t z;
- uint16_t w;
-}vec4i16;
+ uint16_t x;
+ uint16_t y;
+ uint16_t z;
+ uint16_t w;
+} vec4i16;
typedef struct {
- int16_t x;
- int16_t y;
-}vec2i16;
+ int16_t x;
+ int16_t y;
+} vec2i16;
typedef struct {
- vec2 row0;
- vec2 row1;
-}mat2;
+ vec2 row0;
+ vec2 row1;
+} mat2;
// compute length of float vector 2d
-vkvg_inline float vec2_length(vec2 v){
- return sqrtf (v.x*v.x + v.y*v.y);
-}
+vkvg_inline float vec2_length(vec2 v) { return sqrtf(v.x * v.x + v.y * v.y); }
// compute normal direction vector from line defined by 2 points in double precision
-vkvg_inline vec2d vec2d_line_norm(vec2d a, vec2d b)
-{
- vec2d d = {b.x - a.x, b.y - a.y};
- double md = sqrt (d.x*d.x + d.y*d.y);
- d.x/=md;
- d.y/=md;
- return d;
+vkvg_inline vec2d vec2d_line_norm(vec2d a, vec2d b) {
+ vec2d d = {b.x - a.x, b.y - a.y};
+ double md = sqrt(d.x * d.x + d.y * d.y);
+ d.x /= md;
+ d.y /= md;
+ return d;
}
// compute normal direction vector from line defined by 2 points
-vkvg_inline vec2 vec2_line_norm(vec2 a, vec2 b)
-{
- vec2 d = {b.x - a.x, b.y - a.y};
- float md = sqrtf (d.x*d.x + d.y*d.y);
- d.x/=md;
- d.y/=md;
- return d;
+vkvg_inline vec2 vec2_line_norm(vec2 a, vec2 b) {
+ vec2 d = {b.x - a.x, b.y - a.y};
+ float md = sqrtf(d.x * d.x + d.y * d.y);
+ d.x /= md;
+ d.y /= md;
+ return d;
}
// compute sum of two double precision vectors
-vkvg_inline vec2d vec2d_add (vec2d a, vec2d b){
- return (vec2d){a.x + b.x, a.y + b.y};
-}
+vkvg_inline vec2d vec2d_add(vec2d a, vec2d b) { return (vec2d){a.x + b.x, a.y + b.y}; }
// compute subbstraction of two double precision vectors
-vkvg_inline vec2d vec2d_sub (vec2d a, vec2d b){
- return (vec2d){a.x - b.x, a.y - b.y};
-}
+vkvg_inline vec2d vec2d_sub(vec2d a, vec2d b) { return (vec2d){a.x - b.x, a.y - b.y}; }
// multiply 2d vector by scalar
-vkvg_inline vec2d vec2d_mult_s(vec2d a, double m){
- return (vec2d){a.x*m,a.y*m};
-}
-vkvg_inline vec2d vec2d_div_s(vec2d a, double m){
- return (vec2d){a.x/m,a.y/m};
-}
+vkvg_inline vec2d vec2d_mult_s(vec2d a, double m) { return (vec2d){a.x * m, a.y * m}; }
+vkvg_inline vec2d vec2d_div_s(vec2d a, double m) { return (vec2d){a.x / m, a.y / m}; }
// compute length of double vector 2d
-vkvg_inline double vec2d_length(vec2d v){
- return sqrt (v.x*v.x + v.y*v.y);
-}
+vkvg_inline double vec2d_length(vec2d v) { return sqrt(v.x * v.x + v.y * v.y); }
// normalize double vector
-vkvg_inline vec2d vec2d_norm(vec2d a)
-{
- double m = sqrt (a.x*a.x + a.y*a.y);
- return (vec2d){a.x/m, a.y/m};
+vkvg_inline vec2d vec2d_norm(vec2d a) {
+ double m = sqrt(a.x * a.x + a.y * a.y);
+ return (vec2d){a.x / m, a.y / m};
}
// compute perpendicular vector
-vkvg_inline vec2d vec2d_perp (vec2d a){
- return (vec2d){a.y, -a.x};
-}
-vkvg_inline bool vec2d_isnan (vec2d v){
- return (bool)(isnan (v.x) || isnan (v.y));
-}
-
+vkvg_inline vec2d vec2d_perp(vec2d a) { return (vec2d){a.y, -a.x}; }
+vkvg_inline bool vec2d_isnan(vec2d v) { return (bool)(isnan(v.x) || isnan(v.y)); }
// test equality of two single precision vectors
-vkvg_inline bool vec2_equ (vec2 a, vec2 b){
- return (EQUF(a.x,b.x)&EQUF(a.y,b.y));
-}
+vkvg_inline bool vec2_equ(vec2 a, vec2 b) { return (EQUF(a.x, b.x) & EQUF(a.y, b.y)); }
// compute sum of two single precision vectors
-vkvg_inline vec2 vec2_add (vec2 a, vec2 b){
- return (vec2){a.x + b.x, a.y + b.y};
-}
+vkvg_inline vec2 vec2_add(vec2 a, vec2 b) { return (vec2){a.x + b.x, a.y + b.y}; }
// compute subbstraction of two single precision vectors
-vkvg_inline vec2 vec2_sub (vec2 a, vec2 b){
- return (vec2){a.x - b.x, a.y - b.y};
-}
+vkvg_inline vec2 vec2_sub(vec2 a, vec2 b) { return (vec2){a.x - b.x, a.y - b.y}; }
// multiply 2d vector by scalar
-vkvg_inline vec2 vec2_mult_s(vec2 a, float m){
- return (vec2){a.x*m,a.y*m};
-}
+vkvg_inline vec2 vec2_mult_s(vec2 a, float m) { return (vec2){a.x * m, a.y * m}; }
// devide 2d vector by scalar
-vkvg_inline vec2 vec2_div_s(vec2 a, float m){
- return (vec2){a.x/m,a.y/m};
-}
+vkvg_inline vec2 vec2_div_s(vec2 a, float m) { return (vec2){a.x / m, a.y / m}; }
// normalize float vector
-vkvg_inline vec2 vec2_norm(vec2 a)
-{
- float m = sqrtf (a.x*a.x + a.y*a.y);
- return (vec2){a.x/m, a.y/m};
+vkvg_inline vec2 vec2_norm(vec2 a) {
+ float m = sqrtf(a.x * a.x + a.y * a.y);
+ return (vec2){a.x / m, a.y / m};
}
// compute perpendicular vector
-vkvg_inline vec2 vec2_perp (vec2 a){
- return (vec2){a.y, -a.x};
-}
+vkvg_inline vec2 vec2_perp(vec2 a) { return (vec2){a.y, -a.x}; }
// compute opposite of single precision vector
-vkvg_inline void vec2_inv (vec2* v){
- v->x = -v->x;
- v->y = -v->y;
+vkvg_inline void vec2_inv(vec2 *v) {
+ v->x = -v->x;
+ v->y = -v->y;
}
// test if one component of float vector is nan
-vkvg_inline bool vec2_isnan (vec2 v){
- return (bool)(isnan (v.x) || isnan (v.y));
-}
+vkvg_inline bool vec2_isnan(vec2 v) { return (bool)(isnan(v.x) || isnan(v.y)); }
// test if one component of double vector is nan
-vkvg_inline float vec2_dot (vec2 a, vec2 b) {
- return (a.x * b.x) + (a.y * b.y);
-}
-vkvg_inline float vec2_det (vec2 a, vec2 b) {
- return a.x * b.y - a.y * b.x;
-}
-vkvg_inline float vec2_slope (vec2 a, vec2 b) {
- return (b.y - a.y) / (b.x - a.x);
-}
-
+vkvg_inline float vec2_dot(vec2 a, vec2 b) { return (a.x * b.x) + (a.y * b.y); }
+vkvg_inline float vec2_det(vec2 a, vec2 b) { return a.x * b.y - a.y * b.x; }
+vkvg_inline float vec2_slope(vec2 a, vec2 b) { return (b.y - a.y) / (b.x - a.x); }
// convert double precision vector to single precision
-vkvg_inline vec2 vec2d_to_vec2(vec2d vd){
- return (vec2){(float)vd.x,(float)vd.y};
-}
-vkvg_inline bool vec4_equ (vec4 a, vec4 b){
- return (EQUF(a.x,b.x)&EQUF(a.y,b.y)&EQUF(a.z,b.z)&EQUF(a.w,b.w));
-}
-vkvg_inline vec2 mat2_mult_vec2 (mat2 m, vec2 v) {
- return (vec2){
- (m.row0.x * v.x) + (m.row0.y * v.y),
- (m.row1.x * v.x) + (m.row1.y * v.y)
- };
+vkvg_inline vec2 vec2d_to_vec2(vec2d vd) { return (vec2){(float)vd.x, (float)vd.y}; }
+vkvg_inline bool vec4_equ(vec4 a, vec4 b) {
+ return (EQUF(a.x, b.x) & EQUF(a.y, b.y) & EQUF(a.z, b.z) & EQUF(a.w, b.w));
}
-vkvg_inline float mat2_det (mat2* m) {
- return (m->row0.x * m->row1.y) - (m->row0.y * m->row1.y);
+vkvg_inline vec2 mat2_mult_vec2(mat2 m, vec2 v) {
+ return (vec2){(m.row0.x * v.x) + (m.row0.y * v.y), (m.row1.x * v.x) + (m.row1.y * v.y)};
}
+vkvg_inline float mat2_det(mat2 *m) { return (m->row0.x * m->row1.y) - (m->row0.y * m->row1.y); }
#endif
#include "vkh_queue.h"
#ifdef DEBUG
- static vec2 debugLinePoints[1000];
- static uint32_t dlpCount = 0;
- #if defined (VKVG_DBG_UTILS)
- const float DBG_LAB_COLOR_SAV[4] = {1,0,1,1};
- const float DBG_LAB_COLOR_CLIP[4] = {0,1,1,1};
- #endif
+static vec2 debugLinePoints[1000];
+static uint32_t dlpCount = 0;
+#if defined(VKVG_DBG_UTILS)
+const float DBG_LAB_COLOR_SAV[4] = {1, 0, 1, 1};
+const float DBG_LAB_COLOR_CLIP[4] = {0, 1, 1, 1};
+#endif
#endif
-//todo:this could be used to define a default background
+// todo:this could be used to define a default background
static VkClearValue clearValues[3] = {
- { .color.float32 = {0,0,0,0} },
- { .depthStencil = {1.0f, 0} },
- { .color.float32 = {0,0,0,0} }
-};
-
-void _init_ctx (VkvgContext ctx) {
- ctx->lineWidth = 1;
- ctx->miterLimit = 10;
- ctx->curOperator = VKVG_OPERATOR_OVER;
- ctx->curFillRule = VKVG_FILL_RULE_NON_ZERO;
- ctx->bounds = (VkRect2D) {{0,0},{ctx->pSurf->width,ctx->pSurf->height}};
- ctx->pushConsts = (push_constants) {
- {.a = 1},
- {(float)ctx->pSurf->width,(float)ctx->pSurf->height},
- VKVG_PATTERN_TYPE_SOLID,
- 1.0f,
- VKVG_IDENTITY_MATRIX,
- VKVG_IDENTITY_MATRIX
- };
- ctx->clearRect = (VkClearRect) {{{0},{ctx->pSurf->width, ctx->pSurf->height}},0,1};
- ctx->renderPassBeginInfo.framebuffer = ctx->pSurf->fb;
- ctx->renderPassBeginInfo.renderArea.extent.width = ctx->pSurf->width;
- ctx->renderPassBeginInfo.renderArea.extent.height = ctx->pSurf->height;
- ctx->renderPassBeginInfo.pClearValues = clearValues;
-
- LOCK_SURFACE (ctx->pSurf)
-
- if (ctx->pSurf->newSurf)
- ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearAll;
- else
- ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearStencil;
- ctx->pSurf->newSurf = false;
-
- UNLOCK_SURFACE (ctx->pSurf);
-
- vkvg_surface_reference (ctx->pSurf);
-
- if (ctx->dev->samples == VK_SAMPLE_COUNT_1_BIT)
- ctx->renderPassBeginInfo.clearValueCount = 2;
- else
- ctx->renderPassBeginInfo.clearValueCount = 3;
-
- ctx->selectedCharSize = 10 << 6;
- ctx->currentFont = NULL;
- ctx->selectedFontName[0]= 0;
- ctx->pattern = NULL;
- ctx->curColor = 0xff000000;//opaque black
- ctx->cmdStarted = false;
- ctx->curClipState = vkvg_clip_state_none;
- ctx->vertCount = ctx->indCount = 0;
+ {.color.float32 = {0, 0, 0, 0}}, {.depthStencil = {1.0f, 0}}, {.color.float32 = {0, 0, 0, 0}}};
+
+void _init_ctx(VkvgContext ctx) {
+ ctx->lineWidth = 1;
+ ctx->miterLimit = 10;
+ ctx->curOperator = VKVG_OPERATOR_OVER;
+ ctx->curFillRule = VKVG_FILL_RULE_NON_ZERO;
+ ctx->bounds = (VkRect2D){{0, 0}, {ctx->pSurf->width, ctx->pSurf->height}};
+ ctx->pushConsts = (push_constants){{.a = 1},
+ {(float)ctx->pSurf->width, (float)ctx->pSurf->height},
+ VKVG_PATTERN_TYPE_SOLID,
+ 1.0f,
+ VKVG_IDENTITY_MATRIX,
+ VKVG_IDENTITY_MATRIX};
+ ctx->clearRect = (VkClearRect){{{0}, {ctx->pSurf->width, ctx->pSurf->height}}, 0, 1};
+ ctx->renderPassBeginInfo.framebuffer = ctx->pSurf->fb;
+ ctx->renderPassBeginInfo.renderArea.extent.width = ctx->pSurf->width;
+ ctx->renderPassBeginInfo.renderArea.extent.height = ctx->pSurf->height;
+ ctx->renderPassBeginInfo.pClearValues = clearValues;
+
+ LOCK_SURFACE(ctx->pSurf)
+
+ if (ctx->pSurf->newSurf)
+ ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearAll;
+ else
+ ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearStencil;
+ ctx->pSurf->newSurf = false;
+
+ UNLOCK_SURFACE(ctx->pSurf);
+
+ vkvg_surface_reference(ctx->pSurf);
+
+ if (ctx->dev->samples == VK_SAMPLE_COUNT_1_BIT)
+ ctx->renderPassBeginInfo.clearValueCount = 2;
+ else
+ ctx->renderPassBeginInfo.clearValueCount = 3;
+
+ ctx->selectedCharSize = 10 << 6;
+ ctx->currentFont = NULL;
+ ctx->selectedFontName[0] = 0;
+ ctx->pattern = NULL;
+ ctx->curColor = 0xff000000; // opaque black
+ ctx->cmdStarted = false;
+ ctx->curClipState = vkvg_clip_state_none;
+ ctx->vertCount = ctx->indCount = 0;
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- ctx->timelineStep = 0;
+ ctx->timelineStep = 0;
#endif
}
-VkvgContext vkvg_create(VkvgSurface surf)
-{
- VkvgDevice dev = surf->dev;
- VkvgContext ctx = NULL;
+VkvgContext vkvg_create(VkvgSurface surf) {
+ VkvgDevice dev = surf->dev;
+ VkvgContext ctx = NULL;
- if (_device_try_get_cached_context (dev, &ctx) ) {
- ctx->pSurf = surf;
+ if (_device_try_get_cached_context(dev, &ctx)) {
+ ctx->pSurf = surf;
- if (!surf || surf->status) {
- ctx->status = VKVG_STATUS_INVALID_SURFACE;
- return ctx;
- }
+ if (!surf || surf->status) {
+ ctx->status = VKVG_STATUS_INVALID_SURFACE;
+ return ctx;
+ }
- _init_ctx (ctx);
- _update_descriptor_set (ctx, surf->dev->emptyImg, ctx->dsSrc);
- _clear_path (ctx);
- ctx->cmd = ctx->cmdBuffers[0];//current recording buffer
- ctx->status = VKVG_STATUS_SUCCESS;
- return ctx;
- }
- ctx = (vkvg_context*)calloc(1, sizeof(vkvg_context));
+ _init_ctx(ctx);
+ _update_descriptor_set(ctx, surf->dev->emptyImg, ctx->dsSrc);
+ _clear_path(ctx);
+ ctx->cmd = ctx->cmdBuffers[0]; // current recording buffer
+ ctx->status = VKVG_STATUS_SUCCESS;
+ return ctx;
+ }
+ ctx = (vkvg_context *)calloc(1, sizeof(vkvg_context));
- LOG(VKVG_LOG_INFO, "CREATE Context: ctx = %p; surf = %p\n", ctx, surf);
+ LOG(VKVG_LOG_INFO, "CREATE Context: ctx = %p; surf = %p\n", ctx, surf);
- if (!ctx)
- return (VkvgContext)&_no_mem_status;
+ if (!ctx)
+ return (VkvgContext)&_no_mem_status;
- ctx->pSurf = surf;
+ ctx->pSurf = surf;
- if (!surf || surf->status) {
- ctx->status = VKVG_STATUS_INVALID_SURFACE;
- return ctx;
- }
+ if (!surf || surf->status) {
+ ctx->status = VKVG_STATUS_INVALID_SURFACE;
+ return ctx;
+ }
- ctx->sizePoints = VKVG_PTS_SIZE;
- ctx->sizeVertices = ctx->sizeVBO = VKVG_VBO_SIZE;
- ctx->sizeIndices = ctx->sizeIBO = VKVG_IBO_SIZE;
- ctx->sizePathes = VKVG_PATHES_SIZE;
- ctx->renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ ctx->sizePoints = VKVG_PTS_SIZE;
+ ctx->sizeVertices = ctx->sizeVBO = VKVG_VBO_SIZE;
+ ctx->sizeIndices = ctx->sizeIBO = VKVG_IBO_SIZE;
+ ctx->sizePathes = VKVG_PATHES_SIZE;
+ ctx->renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- ctx->dev = surf->dev;
+ ctx->dev = surf->dev;
- _init_ctx (ctx);
+ _init_ctx(ctx);
- ctx->points = (vec2*)malloc (VKVG_VBO_SIZE * sizeof(vec2));
- ctx->pathes = (uint32_t*)malloc (VKVG_PATHES_SIZE * sizeof(uint32_t));
- ctx->vertexCache = (Vertex*)malloc (ctx->sizeVertices * sizeof(Vertex));
- ctx->indexCache = (VKVG_IBO_INDEX_TYPE*)malloc (ctx->sizeIndices * sizeof(VKVG_IBO_INDEX_TYPE));
+ ctx->points = (vec2 *)malloc(VKVG_VBO_SIZE * sizeof(vec2));
+ ctx->pathes = (uint32_t *)malloc(VKVG_PATHES_SIZE * sizeof(uint32_t));
+ ctx->vertexCache = (Vertex *)malloc(ctx->sizeVertices * sizeof(Vertex));
+ ctx->indexCache = (VKVG_IBO_INDEX_TYPE *)malloc(ctx->sizeIndices * sizeof(VKVG_IBO_INDEX_TYPE));
- if (!ctx->points || !ctx->pathes || !ctx->vertexCache || !ctx->indexCache) {
- dev->status = VKVG_STATUS_NO_MEMORY;
- if (ctx->points)
- free(ctx->points);
- if (ctx->pathes)
- free(ctx->pathes);
- if (ctx->vertexCache)
- free(ctx->vertexCache);
- if (ctx->indexCache)
- free(ctx->indexCache);
- return NULL;
- }
+ if (!ctx->points || !ctx->pathes || !ctx->vertexCache || !ctx->indexCache) {
+ dev->status = VKVG_STATUS_NO_MEMORY;
+ if (ctx->points)
+ free(ctx->points);
+ if (ctx->pathes)
+ free(ctx->pathes);
+ if (ctx->vertexCache)
+ free(ctx->vertexCache);
+ if (ctx->indexCache)
+ free(ctx->indexCache);
+ return NULL;
+ }
- //for context to be thread safe, command pool and descriptor pool have to be created in the thread of the context.
- ctx->cmdPool = vkh_cmd_pool_create ((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
+ // for context to be thread safe, command pool and descriptor pool have to be created in the thread of the context.
+ ctx->cmdPool =
+ vkh_cmd_pool_create((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
#ifndef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- ctx->flushFence = vkh_fence_create_signaled ((VkhDevice)ctx->dev);
+ ctx->flushFence = vkh_fence_create_signaled((VkhDevice)ctx->dev);
#endif
- _create_vertices_buff (ctx);
- _create_gradient_buff (ctx);
- _create_cmd_buff (ctx);
- _createDescriptorPool (ctx);
- _init_descriptor_sets (ctx);
- _font_cache_update_context_descset (ctx);
- _update_descriptor_set (ctx, surf->dev->emptyImg, ctx->dsSrc);
- _update_gradient_desc_set(ctx);
+ _create_vertices_buff(ctx);
+ _create_gradient_buff(ctx);
+ _create_cmd_buff(ctx);
+ _createDescriptorPool(ctx);
+ _init_descriptor_sets(ctx);
+ _font_cache_update_context_descset(ctx);
+ _update_descriptor_set(ctx, surf->dev->emptyImg, ctx->dsSrc);
+ _update_gradient_desc_set(ctx);
- _clear_path (ctx);
+ _clear_path(ctx);
- ctx->cmd = ctx->cmdBuffers[0];//current recording buffer
+ ctx->cmd = ctx->cmdBuffers[0]; // current recording buffer
- ctx->references = 1;
- ctx->status = VKVG_STATUS_SUCCESS;
+ ctx->references = 1;
+ ctx->status = VKVG_STATUS_SUCCESS;
- LOG(VKVG_LOG_DBG_ARRAYS, "INIT\tctx = %p; pathes:%ju pts:%ju vch:%d vbo:%d ich:%d ibo:%d\n", ctx, (uint64_t)ctx->sizePathes, (uint64_t)ctx->sizePoints, ctx->sizeVertices, ctx->sizeVBO, ctx->sizeIndices, ctx->sizeIBO);
+ LOG(VKVG_LOG_DBG_ARRAYS, "INIT\tctx = %p; pathes:%ju pts:%ju vch:%d vbo:%d ich:%d ibo:%d\n", ctx,
+ (uint64_t)ctx->sizePathes, (uint64_t)ctx->sizePoints, ctx->sizeVertices, ctx->sizeVBO, ctx->sizeIndices,
+ ctx->sizeIBO);
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_POOL, (uint64_t)ctx->cmdPool, "CTX Cmd Pool");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)ctx->cmdBuffers[0], "CTX Cmd Buff A");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)ctx->cmdBuffers[1], "CTX Cmd Buff B");
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_POOL, (uint64_t)ctx->cmdPool, "CTX Cmd Pool");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)ctx->cmdBuffers[0],
+ "CTX Cmd Buff A");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)ctx->cmdBuffers[1],
+ "CTX Cmd Buff B");
#ifndef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_FENCE, (uint64_t)ctx->flushFence, "CTX Flush Fence");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_FENCE, (uint64_t)ctx->flushFence, "CTX Flush Fence");
#endif
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_POOL, (uint64_t)ctx->descriptorPool, "CTX Descriptor Pool");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsSrc, "CTX DescSet SOURCE");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsFont, "CTX DescSet FONT");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsGrad, "CTX DescSet GRADIENT");
-
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_BUFFER, (uint64_t)ctx->indices.buffer, "CTX Index Buff");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_BUFFER, (uint64_t)ctx->vertices.buffer, "CTX Vertex Buff");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_POOL, (uint64_t)ctx->descriptorPool,
+ "CTX Descriptor Pool");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsSrc,
+ "CTX DescSet SOURCE");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsFont,
+ "CTX DescSet FONT");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsGrad,
+ "CTX DescSet GRADIENT");
+
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_BUFFER, (uint64_t)ctx->indices.buffer, "CTX Index Buff");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_BUFFER, (uint64_t)ctx->vertices.buffer,
+ "CTX Vertex Buff");
#endif
- return ctx;
-}
-void vkvg_flush (VkvgContext ctx){
- if (ctx->status)
- return;
- _flush_cmd_buff (ctx);
- _wait_ctx_flush_end (ctx);
-/*
-#ifdef DEBUG
-
- vec4 red = {0,0,1,1};
- vec4 green = {0,1,0,1};
- vec4 white = {1,1,1,1};
-
- int j = 0;
- while (j < dlpCount) {
- add_line(ctx, debugLinePoints[j], debugLinePoints[j+1],green);
- j+=2;
- add_line(ctx, debugLinePoints[j], debugLinePoints[j+1],red);
- j+=2;
- add_line(ctx, debugLinePoints[j], debugLinePoints[j+1],white);
- j+=2;
- }
- dlpCount = 0;
- CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineLineList);
- CmdDrawIndexed(ctx->cmd, ctx->indCount-ctx->curIndStart, 1, ctx->curIndStart, 0, 1);
- _flush_cmd_buff(ctx);
-#endif
-*/
-}
-
-void _clear_context (VkvgContext ctx) {
- //free saved context stack elmt
- vkvg_context_save_t* next = ctx->pSavedCtxs;
- ctx->pSavedCtxs = NULL;
- while (next != NULL) {
- vkvg_context_save_t* cur = next;
- next = cur->pNext;
- _free_ctx_save (cur);
- }
- //free additional stencil use in save/restore process
- if (ctx->savedStencils) {
- uint8_t curSaveStencil = ctx->curSavBit / 6;
- for (int i=curSaveStencil;i>0;i--)
- vkh_image_destroy(ctx->savedStencils[i-1]);
- free(ctx->savedStencils);
- ctx->savedStencils = NULL;
- ctx->curSavBit = 0;
- }
-
- //remove context from double linked list of context in device
- /*if (ctx->dev->lastCtx == ctx){
- ctx->dev->lastCtx = ctx->pPrev;
- if (ctx->pPrev != NULL)
- ctx->pPrev->pNext = NULL;
- }else if (ctx->pPrev == NULL){
- //first elmt, and it's not last one so pnext is not null
- ctx->pNext->pPrev = NULL;
- }else{
- ctx->pPrev->pNext = ctx->pNext;
- ctx->pNext->pPrev = ctx->pPrev;
- }*/
- if (ctx->dashCount > 0) {
- free(ctx->dashes);
- ctx->dashCount = 0;
- }
-}
-
-void vkvg_destroy (VkvgContext ctx)
-{
- if (ctx->status)
- return;
-
- ctx->references--;
- if (ctx->references > 0)
- return;
-
- LOG(VKVG_LOG_INFO, "DESTROY Context: ctx = %p (status:%d); surf = %p\n", ctx, ctx->status, ctx->pSurf);
-
- vkvg_flush (ctx);
-
- LOG(VKVG_LOG_DBG_ARRAYS, "END\tctx = %p; pathes:%d pts:%d vch:%d vbo:%d ich:%d ibo:%d\n", ctx, ctx->sizePathes, ctx->sizePoints, ctx->sizeVertices, ctx->sizeVBO, ctx->sizeIndices, ctx->sizeIBO);
+ return ctx;
+}
+void vkvg_flush(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+ _flush_cmd_buff(ctx);
+ _wait_ctx_flush_end(ctx);
+ /*
+ #ifdef DEBUG
+
+ vec4 red = {0,0,1,1};
+ vec4 green = {0,1,0,1};
+ vec4 white = {1,1,1,1};
+
+ int j = 0;
+ while (j < dlpCount) {
+ add_line(ctx, debugLinePoints[j], debugLinePoints[j+1],green);
+ j+=2;
+ add_line(ctx, debugLinePoints[j], debugLinePoints[j+1],red);
+ j+=2;
+ add_line(ctx, debugLinePoints[j], debugLinePoints[j+1],white);
+ j+=2;
+ }
+ dlpCount = 0;
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineLineList);
+ CmdDrawIndexed(ctx->cmd, ctx->indCount-ctx->curIndStart, 1, ctx->curIndStart, 0, 1);
+ _flush_cmd_buff(ctx);
+ #endif
+ */
+}
+
+void _clear_context(VkvgContext ctx) {
+ // free saved context stack elmt
+ vkvg_context_save_t *next = ctx->pSavedCtxs;
+ ctx->pSavedCtxs = NULL;
+ while (next != NULL) {
+ vkvg_context_save_t *cur = next;
+ next = cur->pNext;
+ _free_ctx_save(cur);
+ }
+ // free additional stencil use in save/restore process
+ if (ctx->savedStencils) {
+ uint8_t curSaveStencil = ctx->curSavBit / 6;
+ for (int i = curSaveStencil; i > 0; i--)
+ vkh_image_destroy(ctx->savedStencils[i - 1]);
+ free(ctx->savedStencils);
+ ctx->savedStencils = NULL;
+ ctx->curSavBit = 0;
+ }
+
+ // remove context from double linked list of context in device
+ /*if (ctx->dev->lastCtx == ctx){
+ ctx->dev->lastCtx = ctx->pPrev;
+ if (ctx->pPrev != NULL)
+ ctx->pPrev->pNext = NULL;
+ }else if (ctx->pPrev == NULL){
+ //first elmt, and it's not last one so pnext is not null
+ ctx->pNext->pPrev = NULL;
+ }else{
+ ctx->pPrev->pNext = ctx->pNext;
+ ctx->pNext->pPrev = ctx->pPrev;
+ }*/
+ if (ctx->dashCount > 0) {
+ free(ctx->dashes);
+ ctx->dashCount = 0;
+ }
+}
+
+void vkvg_destroy(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+
+ ctx->references--;
+ if (ctx->references > 0)
+ return;
+
+ LOG(VKVG_LOG_INFO, "DESTROY Context: ctx = %p (status:%d); surf = %p\n", ctx, ctx->status, ctx->pSurf);
+
+ vkvg_flush(ctx);
+
+ LOG(VKVG_LOG_DBG_ARRAYS, "END\tctx = %p; pathes:%d pts:%d vch:%d vbo:%d ich:%d ibo:%d\n", ctx, ctx->sizePathes,
+ ctx->sizePoints, ctx->sizeVertices, ctx->sizeVBO, ctx->sizeIndices, ctx->sizeIBO);
#if VKVG_RECORDING
- if (ctx->recording)
- _destroy_recording(ctx->recording);
+ if (ctx->recording)
+ _destroy_recording(ctx->recording);
#endif
- if (ctx->pattern)
- vkvg_pattern_destroy (ctx->pattern);
+ if (ctx->pattern)
+ vkvg_pattern_destroy(ctx->pattern);
- _clear_context (ctx);
+ _clear_context(ctx);
#if VKVG_DBG_STATS
- if (ctx->dev->threadAware)
- mtx_lock (&ctx->dev->mutex);
-
- vkvg_debug_stats_t* dbgstats = &ctx->dev->debug_stats;
- if (dbgstats->sizePoints < ctx->sizePoints)
- dbgstats->sizePoints = ctx->sizePoints;
- if (dbgstats->sizePathes < ctx->sizePathes)
- dbgstats->sizePathes = ctx->sizePathes;
- if (dbgstats->sizeVertices < ctx->sizeVertices)
- dbgstats->sizeVertices = ctx->sizeVertices;
- if (dbgstats->sizeIndices < ctx->sizeIndices)
- dbgstats->sizeIndices = ctx->sizeIndices;
- if (dbgstats->sizeVBO < ctx->sizeVBO)
- dbgstats->sizeVBO = ctx->sizeVBO;
- if (dbgstats->sizeIBO < ctx->sizeIBO)
- dbgstats->sizeIBO = ctx->sizeIBO;
-
- if (ctx->dev->threadAware)
- mtx_unlock (&ctx->dev->mutex);
+ if (ctx->dev->threadAware)
+ mtx_lock(&ctx->dev->mutex);
+
+ vkvg_debug_stats_t *dbgstats = &ctx->dev->debug_stats;
+ if (dbgstats->sizePoints < ctx->sizePoints)
+ dbgstats->sizePoints = ctx->sizePoints;
+ if (dbgstats->sizePathes < ctx->sizePathes)
+ dbgstats->sizePathes = ctx->sizePathes;
+ if (dbgstats->sizeVertices < ctx->sizeVertices)
+ dbgstats->sizeVertices = ctx->sizeVertices;
+ if (dbgstats->sizeIndices < ctx->sizeIndices)
+ dbgstats->sizeIndices = ctx->sizeIndices;
+ if (dbgstats->sizeVBO < ctx->sizeVBO)
+ dbgstats->sizeVBO = ctx->sizeVBO;
+ if (dbgstats->sizeIBO < ctx->sizeIBO)
+ dbgstats->sizeIBO = ctx->sizeIBO;
+
+ if (ctx->dev->threadAware)
+ mtx_unlock(&ctx->dev->mutex);
#endif
- vkvg_surface_destroy(ctx->pSurf);
+ vkvg_surface_destroy(ctx->pSurf);
- if (!ctx->status && ctx->dev->cachedContextCount < VKVG_MAX_CACHED_CONTEXT_COUNT) {
- _device_store_context (ctx);
- return;
- }
+ if (!ctx->status && ctx->dev->cachedContextCount < VKVG_MAX_CACHED_CONTEXT_COUNT) {
+ _device_store_context(ctx);
+ return;
+ }
- _release_context_ressources (ctx);
+ _release_context_ressources(ctx);
}
-void vkvg_set_opacity (VkvgContext ctx, float opacity) {
- if (ctx->status)
- return;
+void vkvg_set_opacity(VkvgContext ctx, float opacity) {
+ if (ctx->status)
+ return;
- if (EQUF(ctx->pushConsts.opacity, opacity))
- return;
+ if (EQUF(ctx->pushConsts.opacity, opacity))
+ return;
- _emit_draw_cmd_undrawn_vertices (ctx);
- ctx->pushConsts.opacity = opacity;
- ctx->pushCstDirty = true;
-}
-float vkvg_get_opacity (VkvgContext ctx) {
- if (ctx->status)
- return 0;
- return ctx->pushConsts.opacity;
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ ctx->pushConsts.opacity = opacity;
+ ctx->pushCstDirty = true;
}
-vkvg_status_t vkvg_status (VkvgContext ctx) {
- return ctx->status;
+float vkvg_get_opacity(VkvgContext ctx) {
+ if (ctx->status)
+ return 0;
+ return ctx->pushConsts.opacity;
}
-VkvgContext vkvg_reference (VkvgContext ctx) {
- if (!ctx->status)
- ctx->references++;
- return ctx;
+vkvg_status_t vkvg_status(VkvgContext ctx) { return ctx->status; }
+VkvgContext vkvg_reference(VkvgContext ctx) {
+ if (!ctx->status)
+ ctx->references++;
+ return ctx;
}
-uint32_t vkvg_get_reference_count (VkvgContext ctx) {
- if (ctx->status)
- return 0;
- return ctx->references;
+uint32_t vkvg_get_reference_count(VkvgContext ctx) {
+ if (ctx->status)
+ return 0;
+ return ctx->references;
}
-void vkvg_new_sub_path (VkvgContext ctx){
- if (ctx->status)
- return;
+void vkvg_new_sub_path(VkvgContext ctx) {
+ if (ctx->status)
+ return;
- RECORD(ctx, VKVG_CMD_NEW_SUB_PATH);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: new_sub_path:\n");
+ RECORD(ctx, VKVG_CMD_NEW_SUB_PATH);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: new_sub_path:\n");
- _finish_path(ctx);
+ _finish_path(ctx);
}
-void vkvg_new_path (VkvgContext ctx){
- if (ctx->status)
- return;
+void vkvg_new_path(VkvgContext ctx) {
+ if (ctx->status)
+ return;
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: new_path:\n");
-
- _clear_path(ctx);
- RECORD(ctx, VKVG_CMD_NEW_PATH);
-}
-void vkvg_close_path (VkvgContext ctx){
- if (ctx->status)
- return;
-
- RECORD(ctx, VKVG_CMD_CLOSE_PATH);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: close_path:\n");
-
- if (ctx->pathes[ctx->pathPtr] & PATH_CLOSED_BIT) //already closed
- return;
- //check if at least 3 points are present
- if (ctx->pathes[ctx->pathPtr] < 3)
- return;
-
- //prevent closing on the same point
- if (vec2_equ(ctx->points[ctx->pointCount-1],
- ctx->points[ctx->pointCount - ctx->pathes[ctx->pathPtr]])) {
- if (ctx->pathes[ctx->pathPtr] < 4)//ensure enough points left for closing
- return;
- _remove_last_point(ctx);
- }
-
- ctx->pathes[ctx->pathPtr] |= PATH_CLOSED_BIT;
-
- _finish_path(ctx);
-}
-void vkvg_rel_line_to (VkvgContext ctx, float dx, float dy){
- if (ctx->status)
- return;
-
- RECORD(ctx, VKVG_CMD_REL_LINE_TO, dx, dy);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: rel_line_to: %f, %f\n", dx, dy);
-
- if (_current_path_is_empty(ctx))
- _add_point(ctx, 0, 0);
- vec2 cp = _get_current_position(ctx);
- _line_to(ctx, cp.x + dx, cp.y + dy);
-}
-void vkvg_line_to (VkvgContext ctx, float x, float y)
-{
- if (ctx->status)
- return;
-
- RECORD(ctx, VKVG_CMD_LINE_TO, x, y);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: line_to: %f, %f\n", x, y);
- _line_to(ctx, x, y);
-}
-void vkvg_arc (VkvgContext ctx, float xc, float yc, float radius, float a1, float a2){
- if (ctx->status)
- return;
-
- RECORD(ctx, VKVG_CMD_ARC, xc, yc, radius, a1, a2);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: arc: %f,%f %f %f %f\n", xc, yc, radius, a1, a2);
-
- while (a2 < a1)//positive arc must have a1<a2
- a2 += 2.f*M_PIF;
-
- if (a2 - a1 > 2.f * M_PIF) //limit arc to 2PI
- a2 = a1 + 2.f * M_PIF;
-
- vec2 v = {cosf(a1)*radius + xc, sinf(a1)*radius + yc};
-
- float step = _get_arc_step(ctx, radius);
- float a = a1;
-
- if (_current_path_is_empty(ctx)){
- _set_curve_start (ctx);
- _add_point (ctx, v.x, v.y);
- if (!ctx->pathPtr)
- ctx->simpleConvex = true;
- else
- ctx->simpleConvex = false;
- }else{
- _line_to(ctx, v.x, v.y);
- _set_curve_start (ctx);
- ctx->simpleConvex = false;
- }
-
- a+=step;
-
- if (EQUF(a2, a1))
- return;
-
- while(a < a2){
- v.x = cosf(a)*radius + xc;
- v.y = sinf(a)*radius + yc;
- _add_point (ctx, v.x, v.y);
- a+=step;
- }
-
- if (EQUF(a2-a1,M_PIF*2.f)){//if arc is complete circle, last point is the same as the first one
- _set_curve_end(ctx);
- vkvg_close_path(ctx);
- return;
- }
- a = a2;
- //vec2 lastP = v;
- v.x = cosf(a)*radius + xc;
- v.y = sinf(a)*radius + yc;
- //if (!vec2_equ (v,lastP))//this test should not be required
- _add_point (ctx, v.x, v.y);
- _set_curve_end(ctx);
-}
-void vkvg_arc_negative (VkvgContext ctx, float xc, float yc, float radius, float a1, float a2) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_ARC_NEG, xc, yc, radius, a1, a2);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: %f,%f %f %f %f\n", xc, yc, radius, a1, a2);
- while (a2 > a1)
- a2 -= 2.f*M_PIF;
- if (a1 - a2 > a1 + 2.f * M_PIF) //limit arc to 2PI
- a2 = a1 - 2.f * M_PIF;
-
- vec2 v = {cosf(a1)*radius + xc, sinf(a1)*radius + yc};
-
- float step = _get_arc_step(ctx, radius);
- float a = a1;
-
- if (_current_path_is_empty(ctx)){
- _set_curve_start (ctx);
- _add_point (ctx, v.x, v.y);
- if (!ctx->pathPtr)
- ctx->simpleConvex = true;
- else
- ctx->simpleConvex = false;
- }else{
- _line_to(ctx, v.x, v.y);
- _set_curve_start (ctx);
- ctx->simpleConvex = false;
- }
-
- a-=step;
-
- if (EQUF(a2, a1))
- return;
-
- while(a > a2){
- v.x = cosf(a)*radius + xc;
- v.y = sinf(a)*radius + yc;
- _add_point (ctx,v.x,v.y);
- a-=step;
- }
-
- if (EQUF(a1-a2,M_PIF*2.f)){//if arc is complete circle, last point is the same as the first one
- _set_curve_end(ctx);
- vkvg_close_path(ctx);
- return;
- }
-
- a = a2;
- //vec2 lastP = v;
- v.x = cosf(a)*radius + xc;
- v.y = sinf(a)*radius + yc;
- //if (!vec2_equ (v,lastP))
- _add_point (ctx, v.x, v.y);
- _set_curve_end(ctx);
-}
-void vkvg_rel_move_to (VkvgContext ctx, float x, float y)
-{
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_REL_MOVE_TO, x, y);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: rel_mote_to: %f, %f\n", x, y);
- if (_current_path_is_empty(ctx))
- _add_point(ctx, 0, 0);
- vec2 cp = _get_current_position(ctx);
- _finish_path(ctx);
- _add_point (ctx, cp.x + x, cp.y + y);
-}
-void vkvg_move_to (VkvgContext ctx, float x, float y)
-{
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_MOVE_TO, x, y);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: move_to: %f,%f\n", x, y);
- _finish_path(ctx);
- _add_point (ctx, x, y);
-}
-bool vkvg_has_current_point (VkvgContext ctx) {
- if (ctx->status)
- return false;
- return !_current_path_is_empty(ctx);
-}
-void vkvg_get_current_point (VkvgContext ctx, float* x, float* y) {
- if (ctx->status || _current_path_is_empty(ctx)) {
- *x = *y = 0;
- return;
- }
- vec2 cp = _get_current_position(ctx);
- *x = cp.x;
- *y = cp.y;
-}
-void _curve_to (VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) {
- //prevent running _recursive_bezier when all 4 curve points are equal
- if (EQUF(x1,x2) && EQUF(x2,x3) && EQUF(y1,y2) && EQUF(y2,y3)) {
- if (_current_path_is_empty(ctx) || (EQUF(_get_current_position(ctx).x,x1) && EQUF(_get_current_position(ctx).y,y1)))
- return;
- }
- ctx->simpleConvex = false;
- _set_curve_start (ctx);
- if (_current_path_is_empty(ctx))
- _add_point(ctx, x1, y1);
-
- vec2 cp = _get_current_position(ctx);
-
- //compute dyn distanceTolerance depending on current scale
- float sx = 1, sy = 1;
- vkvg_matrix_get_scale (&ctx->pushConsts.mat, &sx, &sy);
- float distanceTolerance = fabs(0.25f / fmaxf(sx,sy));
-
- _recursive_bezier (ctx, distanceTolerance, cp.x, cp.y, x1, y1, x2, y2, x3, y3, 0);
- /*cp.x = x3;
- cp.y = y3;
- if (!vec2_equ(ctx->points[ctx->pointCount-1],cp))*/
- _add_point(ctx,x3,y3);
- _set_curve_end (ctx);
-}
-const double quadraticFact = 2.0/3.0;
-void _quadratic_to (VkvgContext ctx, float x1, float y1, float x2, float y2) {
- float x0, y0;
- if (_current_path_is_empty(ctx)) {
- x0 = x1;
- y0 = y1;
- } else
- vkvg_get_current_point (ctx, &x0, &y0);
- _curve_to (ctx,
- x0 + (x1 - x0) * quadraticFact,
- y0 + (y1 - y0) * quadraticFact,
- x2 + (x1 - x2) * quadraticFact,
- y2 + (y1 - y2) * quadraticFact,
- x2, y2);
-}
-void vkvg_quadratic_to (VkvgContext ctx, float x1, float y1, float x2, float y2) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_QUADRATIC_TO, x1, y1, x2, y2);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: quadratic_to: %f, %f, %f, %f\n", x1, y1, x2, y2);
- _quadratic_to(ctx, x1, y1, x2, y2);
-}
-void vkvg_rel_quadratic_to (VkvgContext ctx, float x1, float y1, float x2, float y2) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_REL_QUADRATIC_TO, x1, y1, x2, y2);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: rel_quadratic_to: %f, %f, %f, %f\n", x1, y1, x2, y2);
- vec2 cp = _get_current_position(ctx);
- _quadratic_to (ctx, cp.x + x1, cp.y + y1, cp.x + x2, cp.y + y2);
-}
-void vkvg_curve_to (VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_CURVE_TO, x1, y1, x2, y2, x3, y3);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: curve_to %f,%f %f,%f %f,%f:\n", x1, y1, x2, y2, x3, y3);
- _curve_to (ctx, x1, y1, x2, y2, x3, y3);
-}
-void vkvg_rel_curve_to (VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) {
- if (ctx->status)
- return;
- if (_current_path_is_empty(ctx)) {
- ctx->status = VKVG_STATUS_NO_CURRENT_POINT;
- return;
- }
- RECORD(ctx, (uint32_t)VKVG_CMD_REL_CURVE_TO, x1, y1, x2, y2, x3, y3);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: rel curve_to %f,%f %f,%f %f,%f:\n", x1, y1, x2, y2, x3, y3);
- vec2 cp = _get_current_position(ctx);
- _curve_to (ctx, cp.x + x1, cp.y + y1, cp.x + x2, cp.y + y2, cp.x + x3, cp.y + y3);
-}
-void vkvg_fill_rectangle (VkvgContext ctx, float x, float y, float w, float h){
- if (ctx->status)
- return;
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: fill_rectangle:\n");
- _vao_add_rectangle (ctx,x,y,w,h);
- //_record_draw_cmd(ctx);
-}
-
-vkvg_status_t vkvg_rectangle (VkvgContext ctx, float x, float y, float w, float h){
- if (ctx->status)
- return ctx->status;
- RECORD2(ctx, VKVG_CMD_RECTANGLE, x, y, w, h);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: rectangle: %f,%f,%f,%f\n", x, y, w, h);
- _finish_path (ctx);
-
- if (w <= 0 || h <= 0)
- return VKVG_STATUS_INVALID_RECT;
-
- _add_point (ctx, x, y);
- _add_point (ctx, x + w, y);
- _add_point (ctx, x + w, y + h);
- _add_point (ctx, x, y + h);
-
- ctx->pathes[ctx->pathPtr] |= (PATH_CLOSED_BIT|PATH_IS_CONVEX_BIT);
-
- _finish_path(ctx);
- return VKVG_STATUS_SUCCESS;
-}
-vkvg_status_t vkvg_rounded_rectangle (VkvgContext ctx, float x, float y, float w, float h, float radius){
- if (ctx->status)
- return ctx->status;
- LOG(VKVG_LOG_INFO_CMD, "CMD: rounded_rectangle:\n");
- _finish_path (ctx);
-
- if (w <= 0 || h <= 0)
- return VKVG_STATUS_INVALID_RECT;
-
- if ((radius > w / 2.0f) || (radius > h / 2.0f))
- radius = fmin (w / 2.0f, h / 2.0f);
-
- vkvg_move_to(ctx, x, y + radius);
- vkvg_arc(ctx, x + radius, y + radius, radius, M_PIF, -M_PIF_2);
- vkvg_line_to(ctx, x + w - radius, y);
- vkvg_arc(ctx, x + w - radius, y + radius, radius, -M_PIF_2, 0);
- vkvg_line_to(ctx, x + w, y + h - radius);
- vkvg_arc(ctx, x + w - radius, y + h - radius, radius, 0, M_PIF_2);
- vkvg_line_to(ctx, x + radius, y + h);
- vkvg_arc(ctx, x + radius, y + h - radius, radius, M_PIF_2, M_PIF);
- vkvg_line_to(ctx, x, y + radius);
- vkvg_close_path(ctx);
-
- return VKVG_STATUS_SUCCESS;
-}
-void vkvg_rounded_rectangle2 (VkvgContext ctx, float x, float y, float w, float h, float rx, float ry){
- if (ctx->status)
- return;
- LOG(VKVG_LOG_INFO_CMD, "CMD: rounded_rectangle2:\n");
- vkvg_move_to (ctx, x+rx, y);
- vkvg_line_to (ctx, x+w-rx, y);
- vkvg_elliptic_arc_to(ctx, x+w, y+ry, false, true, rx, ry, 0);
-
- vkvg_line_to (ctx, x+w, y+h-ry);
- vkvg_elliptic_arc_to(ctx, x+w-rx, y+h, false, true, rx, ry, 0);
-
- vkvg_line_to (ctx, x+rx, y+h);
- vkvg_elliptic_arc_to(ctx, x, y+h-ry , false, true, rx, ry, 0);
-
- vkvg_line_to (ctx, x, y+ry);
- vkvg_elliptic_arc_to(ctx, x+rx, y , false, true, rx, ry, 0);
-
- vkvg_close_path(ctx);
-}
-void vkvg_path_extents (VkvgContext ctx, float *x1, float *y1, float *x2, float *y2) {
- if (ctx->status)
- return;
-
- _finish_path(ctx);
-
- if (!ctx->pathPtr) {//no path
- *x1 = *x2 = *y1 = *y2 = 0;
- return;
- }
-
- _vkvg_path_extents(ctx, false, x1, y1, x2, y2);
-}
-
-vkvg_clip_state_t _get_previous_clip_state (VkvgContext ctx) {
- if (!ctx->pSavedCtxs)//no clip saved => clear
- return vkvg_clip_state_clear;
- return ctx->pSavedCtxs->clippingState;
-}
-static const VkClearAttachment clearStencil = {VK_IMAGE_ASPECT_STENCIL_BIT, 1, {{{0}}}};
-static const VkClearAttachment clearColorAttach = {VK_IMAGE_ASPECT_COLOR_BIT, 0, {{{0}}}};
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: new_path:\n");
+
+ _clear_path(ctx);
+ RECORD(ctx, VKVG_CMD_NEW_PATH);
+}
+void vkvg_close_path(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+
+ RECORD(ctx, VKVG_CMD_CLOSE_PATH);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: close_path:\n");
+
+ if (ctx->pathes[ctx->pathPtr] & PATH_CLOSED_BIT) // already closed
+ return;
+ // check if at least 3 points are present
+ if (ctx->pathes[ctx->pathPtr] < 3)
+ return;
+
+ // prevent closing on the same point
+ if (vec2_equ(ctx->points[ctx->pointCount - 1], ctx->points[ctx->pointCount - ctx->pathes[ctx->pathPtr]])) {
+ if (ctx->pathes[ctx->pathPtr] < 4) // ensure enough points left for closing
+ return;
+ _remove_last_point(ctx);
+ }
+
+ ctx->pathes[ctx->pathPtr] |= PATH_CLOSED_BIT;
+
+ _finish_path(ctx);
+}
+void vkvg_rel_line_to(VkvgContext ctx, float dx, float dy) {
+ if (ctx->status)
+ return;
+
+ RECORD(ctx, VKVG_CMD_REL_LINE_TO, dx, dy);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: rel_line_to: %f, %f\n", dx, dy);
+
+ if (_current_path_is_empty(ctx))
+ _add_point(ctx, 0, 0);
+ vec2 cp = _get_current_position(ctx);
+ _line_to(ctx, cp.x + dx, cp.y + dy);
+}
+void vkvg_line_to(VkvgContext ctx, float x, float y) {
+ if (ctx->status)
+ return;
+
+ RECORD(ctx, VKVG_CMD_LINE_TO, x, y);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: line_to: %f, %f\n", x, y);
+ _line_to(ctx, x, y);
+}
+void vkvg_arc(VkvgContext ctx, float xc, float yc, float radius, float a1, float a2) {
+ if (ctx->status)
+ return;
+
+ RECORD(ctx, VKVG_CMD_ARC, xc, yc, radius, a1, a2);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: arc: %f,%f %f %f %f\n", xc, yc, radius, a1, a2);
+
+ while (a2 < a1) // positive arc must have a1<a2
+ a2 += 2.f * M_PIF;
+
+ if (a2 - a1 > 2.f * M_PIF) // limit arc to 2PI
+ a2 = a1 + 2.f * M_PIF;
+
+ vec2 v = {cosf(a1) * radius + xc, sinf(a1) * radius + yc};
+
+ float step = _get_arc_step(ctx, radius);
+ float a = a1;
+
+ if (_current_path_is_empty(ctx)) {
+ _set_curve_start(ctx);
+ _add_point(ctx, v.x, v.y);
+ if (!ctx->pathPtr)
+ ctx->simpleConvex = true;
+ else
+ ctx->simpleConvex = false;
+ } else {
+ _line_to(ctx, v.x, v.y);
+ _set_curve_start(ctx);
+ ctx->simpleConvex = false;
+ }
+
+ a += step;
+
+ if (EQUF(a2, a1))
+ return;
+
+ while (a < a2) {
+ v.x = cosf(a) * radius + xc;
+ v.y = sinf(a) * radius + yc;
+ _add_point(ctx, v.x, v.y);
+ a += step;
+ }
+
+ if (EQUF(a2 - a1, M_PIF * 2.f)) { // if arc is complete circle, last point is the same as the first one
+ _set_curve_end(ctx);
+ vkvg_close_path(ctx);
+ return;
+ }
+ a = a2;
+ // vec2 lastP = v;
+ v.x = cosf(a) * radius + xc;
+ v.y = sinf(a) * radius + yc;
+ // if (!vec2_equ (v,lastP))//this test should not be required
+ _add_point(ctx, v.x, v.y);
+ _set_curve_end(ctx);
+}
+void vkvg_arc_negative(VkvgContext ctx, float xc, float yc, float radius, float a1, float a2) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_ARC_NEG, xc, yc, radius, a1, a2);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: %f,%f %f %f %f\n", xc, yc, radius, a1, a2);
+ while (a2 > a1)
+ a2 -= 2.f * M_PIF;
+ if (a1 - a2 > a1 + 2.f * M_PIF) // limit arc to 2PI
+ a2 = a1 - 2.f * M_PIF;
+
+ vec2 v = {cosf(a1) * radius + xc, sinf(a1) * radius + yc};
+
+ float step = _get_arc_step(ctx, radius);
+ float a = a1;
+
+ if (_current_path_is_empty(ctx)) {
+ _set_curve_start(ctx);
+ _add_point(ctx, v.x, v.y);
+ if (!ctx->pathPtr)
+ ctx->simpleConvex = true;
+ else
+ ctx->simpleConvex = false;
+ } else {
+ _line_to(ctx, v.x, v.y);
+ _set_curve_start(ctx);
+ ctx->simpleConvex = false;
+ }
+
+ a -= step;
+
+ if (EQUF(a2, a1))
+ return;
+
+ while (a > a2) {
+ v.x = cosf(a) * radius + xc;
+ v.y = sinf(a) * radius + yc;
+ _add_point(ctx, v.x, v.y);
+ a -= step;
+ }
+
+ if (EQUF(a1 - a2, M_PIF * 2.f)) { // if arc is complete circle, last point is the same as the first one
+ _set_curve_end(ctx);
+ vkvg_close_path(ctx);
+ return;
+ }
+
+ a = a2;
+ // vec2 lastP = v;
+ v.x = cosf(a) * radius + xc;
+ v.y = sinf(a) * radius + yc;
+ // if (!vec2_equ (v,lastP))
+ _add_point(ctx, v.x, v.y);
+ _set_curve_end(ctx);
+}
+void vkvg_rel_move_to(VkvgContext ctx, float x, float y) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_REL_MOVE_TO, x, y);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: rel_mote_to: %f, %f\n", x, y);
+ if (_current_path_is_empty(ctx))
+ _add_point(ctx, 0, 0);
+ vec2 cp = _get_current_position(ctx);
+ _finish_path(ctx);
+ _add_point(ctx, cp.x + x, cp.y + y);
+}
+void vkvg_move_to(VkvgContext ctx, float x, float y) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_MOVE_TO, x, y);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: move_to: %f,%f\n", x, y);
+ _finish_path(ctx);
+ _add_point(ctx, x, y);
+}
+bool vkvg_has_current_point(VkvgContext ctx) {
+ if (ctx->status)
+ return false;
+ return !_current_path_is_empty(ctx);
+}
+void vkvg_get_current_point(VkvgContext ctx, float *x, float *y) {
+ if (ctx->status || _current_path_is_empty(ctx)) {
+ *x = *y = 0;
+ return;
+ }
+ vec2 cp = _get_current_position(ctx);
+ *x = cp.x;
+ *y = cp.y;
+}
+void _curve_to(VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) {
+ // prevent running _recursive_bezier when all 4 curve points are equal
+ if (EQUF(x1, x2) && EQUF(x2, x3) && EQUF(y1, y2) && EQUF(y2, y3)) {
+ if (_current_path_is_empty(ctx) ||
+ (EQUF(_get_current_position(ctx).x, x1) && EQUF(_get_current_position(ctx).y, y1)))
+ return;
+ }
+ ctx->simpleConvex = false;
+ _set_curve_start(ctx);
+ if (_current_path_is_empty(ctx))
+ _add_point(ctx, x1, y1);
+
+ vec2 cp = _get_current_position(ctx);
+
+ // compute dyn distanceTolerance depending on current scale
+ float sx = 1, sy = 1;
+ vkvg_matrix_get_scale(&ctx->pushConsts.mat, &sx, &sy);
+ float distanceTolerance = fabs(0.25f / fmaxf(sx, sy));
+
+ _recursive_bezier(ctx, distanceTolerance, cp.x, cp.y, x1, y1, x2, y2, x3, y3, 0);
+ /*cp.x = x3;
+ cp.y = y3;
+ if (!vec2_equ(ctx->points[ctx->pointCount-1],cp))*/
+ _add_point(ctx, x3, y3);
+ _set_curve_end(ctx);
+}
+const double quadraticFact = 2.0 / 3.0;
+void _quadratic_to(VkvgContext ctx, float x1, float y1, float x2, float y2) {
+ float x0, y0;
+ if (_current_path_is_empty(ctx)) {
+ x0 = x1;
+ y0 = y1;
+ } else
+ vkvg_get_current_point(ctx, &x0, &y0);
+ _curve_to(ctx, x0 + (x1 - x0) * quadraticFact, y0 + (y1 - y0) * quadraticFact, x2 + (x1 - x2) * quadraticFact,
+ y2 + (y1 - y2) * quadraticFact, x2, y2);
+}
+void vkvg_quadratic_to(VkvgContext ctx, float x1, float y1, float x2, float y2) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_QUADRATIC_TO, x1, y1, x2, y2);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: quadratic_to: %f, %f, %f, %f\n", x1, y1, x2, y2);
+ _quadratic_to(ctx, x1, y1, x2, y2);
+}
+void vkvg_rel_quadratic_to(VkvgContext ctx, float x1, float y1, float x2, float y2) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_REL_QUADRATIC_TO, x1, y1, x2, y2);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: rel_quadratic_to: %f, %f, %f, %f\n", x1, y1, x2, y2);
+ vec2 cp = _get_current_position(ctx);
+ _quadratic_to(ctx, cp.x + x1, cp.y + y1, cp.x + x2, cp.y + y2);
+}
+void vkvg_curve_to(VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_CURVE_TO, x1, y1, x2, y2, x3, y3);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: curve_to %f,%f %f,%f %f,%f:\n", x1, y1, x2, y2, x3, y3);
+ _curve_to(ctx, x1, y1, x2, y2, x3, y3);
+}
+void vkvg_rel_curve_to(VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) {
+ if (ctx->status)
+ return;
+ if (_current_path_is_empty(ctx)) {
+ ctx->status = VKVG_STATUS_NO_CURRENT_POINT;
+ return;
+ }
+ RECORD(ctx, (uint32_t)VKVG_CMD_REL_CURVE_TO, x1, y1, x2, y2, x3, y3);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: rel curve_to %f,%f %f,%f %f,%f:\n", x1, y1, x2, y2, x3, y3);
+ vec2 cp = _get_current_position(ctx);
+ _curve_to(ctx, cp.x + x1, cp.y + y1, cp.x + x2, cp.y + y2, cp.x + x3, cp.y + y3);
+}
+void vkvg_fill_rectangle(VkvgContext ctx, float x, float y, float w, float h) {
+ if (ctx->status)
+ return;
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: fill_rectangle:\n");
+ _vao_add_rectangle(ctx, x, y, w, h);
+ //_record_draw_cmd(ctx);
+}
+
+vkvg_status_t vkvg_rectangle(VkvgContext ctx, float x, float y, float w, float h) {
+ if (ctx->status)
+ return ctx->status;
+ RECORD2(ctx, VKVG_CMD_RECTANGLE, x, y, w, h);
+ LOG(VKVG_LOG_INFO_CMD, "\tCMD: rectangle: %f,%f,%f,%f\n", x, y, w, h);
+ _finish_path(ctx);
+
+ if (w <= 0 || h <= 0)
+ return VKVG_STATUS_INVALID_RECT;
+
+ _add_point(ctx, x, y);
+ _add_point(ctx, x + w, y);
+ _add_point(ctx, x + w, y + h);
+ _add_point(ctx, x, y + h);
+
+ ctx->pathes[ctx->pathPtr] |= (PATH_CLOSED_BIT | PATH_IS_CONVEX_BIT);
+
+ _finish_path(ctx);
+ return VKVG_STATUS_SUCCESS;
+}
+vkvg_status_t vkvg_rounded_rectangle(VkvgContext ctx, float x, float y, float w, float h, float radius) {
+ if (ctx->status)
+ return ctx->status;
+ LOG(VKVG_LOG_INFO_CMD, "CMD: rounded_rectangle:\n");
+ _finish_path(ctx);
+
+ if (w <= 0 || h <= 0)
+ return VKVG_STATUS_INVALID_RECT;
+
+ if ((radius > w / 2.0f) || (radius > h / 2.0f))
+ radius = fmin(w / 2.0f, h / 2.0f);
+
+ vkvg_move_to(ctx, x, y + radius);
+ vkvg_arc(ctx, x + radius, y + radius, radius, M_PIF, -M_PIF_2);
+ vkvg_line_to(ctx, x + w - radius, y);
+ vkvg_arc(ctx, x + w - radius, y + radius, radius, -M_PIF_2, 0);
+ vkvg_line_to(ctx, x + w, y + h - radius);
+ vkvg_arc(ctx, x + w - radius, y + h - radius, radius, 0, M_PIF_2);
+ vkvg_line_to(ctx, x + radius, y + h);
+ vkvg_arc(ctx, x + radius, y + h - radius, radius, M_PIF_2, M_PIF);
+ vkvg_line_to(ctx, x, y + radius);
+ vkvg_close_path(ctx);
+
+ return VKVG_STATUS_SUCCESS;
+}
+void vkvg_rounded_rectangle2(VkvgContext ctx, float x, float y, float w, float h, float rx, float ry) {
+ if (ctx->status)
+ return;
+ LOG(VKVG_LOG_INFO_CMD, "CMD: rounded_rectangle2:\n");
+ vkvg_move_to(ctx, x + rx, y);
+ vkvg_line_to(ctx, x + w - rx, y);
+ vkvg_elliptic_arc_to(ctx, x + w, y + ry, false, true, rx, ry, 0);
+
+ vkvg_line_to(ctx, x + w, y + h - ry);
+ vkvg_elliptic_arc_to(ctx, x + w - rx, y + h, false, true, rx, ry, 0);
+
+ vkvg_line_to(ctx, x + rx, y + h);
+ vkvg_elliptic_arc_to(ctx, x, y + h - ry, false, true, rx, ry, 0);
+
+ vkvg_line_to(ctx, x, y + ry);
+ vkvg_elliptic_arc_to(ctx, x + rx, y, false, true, rx, ry, 0);
+
+ vkvg_close_path(ctx);
+}
+void vkvg_path_extents(VkvgContext ctx, float *x1, float *y1, float *x2, float *y2) {
+ if (ctx->status)
+ return;
+
+ _finish_path(ctx);
+
+ if (!ctx->pathPtr) { // no path
+ *x1 = *x2 = *y1 = *y2 = 0;
+ return;
+ }
+
+ _vkvg_path_extents(ctx, false, x1, y1, x2, y2);
+}
+
+vkvg_clip_state_t _get_previous_clip_state(VkvgContext ctx) {
+ if (!ctx->pSavedCtxs) // no clip saved => clear
+ return vkvg_clip_state_clear;
+ return ctx->pSavedCtxs->clippingState;
+}
+static const VkClearAttachment clearStencil = {VK_IMAGE_ASPECT_STENCIL_BIT, 1, {{{0}}}};
+static const VkClearAttachment clearColorAttach = {VK_IMAGE_ASPECT_COLOR_BIT, 0, {{{0}}}};
-void _reset_clip (VkvgContext ctx) {
- _emit_draw_cmd_undrawn_vertices(ctx);
- if (!ctx->cmdStarted) {
- //if command buffer is not already started and in a renderpass, we use the renderpass
- //with the loadop clear for stencil
- ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearStencil;
- //force run of one renderpass (even empty) to perform clear load op
- _start_cmd_for_render_pass(ctx);
- return;
- }
- vkCmdClearAttachments(ctx->cmd, 1, &clearStencil, 1, &ctx->clearRect);
+void _reset_clip(VkvgContext ctx) {
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ if (!ctx->cmdStarted) {
+ // if command buffer is not already started and in a renderpass, we use the renderpass
+ // with the loadop clear for stencil
+ ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearStencil;
+ // force run of one renderpass (even empty) to perform clear load op
+ _start_cmd_for_render_pass(ctx);
+ return;
+ }
+ vkCmdClearAttachments(ctx->cmd, 1, &clearStencil, 1, &ctx->clearRect);
}
-void vkvg_reset_clip (VkvgContext ctx){
- if (ctx->status)
- return;
+void vkvg_reset_clip(VkvgContext ctx) {
+ if (ctx->status)
+ return;
- RECORD(ctx, VKVG_CMD_RESET_CLIP);
+ RECORD(ctx, VKVG_CMD_RESET_CLIP);
- if (ctx->curClipState == vkvg_clip_state_clear)
- return;
- if (_get_previous_clip_state(ctx) == vkvg_clip_state_clear)
- ctx->curClipState = vkvg_clip_state_none;
- else
- ctx->curClipState = vkvg_clip_state_clear;
+ if (ctx->curClipState == vkvg_clip_state_clear)
+ return;
+ if (_get_previous_clip_state(ctx) == vkvg_clip_state_clear)
+ ctx->curClipState = vkvg_clip_state_none;
+ else
+ ctx->curClipState = vkvg_clip_state_clear;
- _reset_clip (ctx);
+ _reset_clip(ctx);
}
-void vkvg_clear (VkvgContext ctx){
- if (ctx->status)
- return;
+void vkvg_clear(VkvgContext ctx) {
+ if (ctx->status)
+ return;
- RECORD(ctx, VKVG_CMD_CLEAR);
+ RECORD(ctx, VKVG_CMD_CLEAR);
- if (_get_previous_clip_state(ctx) == vkvg_clip_state_clear)
- ctx->curClipState = vkvg_clip_state_none;
- else
- ctx->curClipState = vkvg_clip_state_clear;
+ if (_get_previous_clip_state(ctx) == vkvg_clip_state_clear)
+ ctx->curClipState = vkvg_clip_state_none;
+ else
+ ctx->curClipState = vkvg_clip_state_clear;
- _emit_draw_cmd_undrawn_vertices(ctx);
- if (!ctx->cmdStarted) {
- ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearAll;
- _start_cmd_for_render_pass(ctx);
- return;
- }
- VkClearAttachment ca[2] = {clearColorAttach, clearStencil};
- vkCmdClearAttachments(ctx->cmd, 2, ca, 1, &ctx->clearRect);
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ if (!ctx->cmdStarted) {
+ ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearAll;
+ _start_cmd_for_render_pass(ctx);
+ return;
+ }
+ VkClearAttachment ca[2] = {clearColorAttach, clearStencil};
+ vkCmdClearAttachments(ctx->cmd, 2, ca, 1, &ctx->clearRect);
}
-void _clip_preserve (VkvgContext ctx){
- _finish_path(ctx);
+void _clip_preserve(VkvgContext ctx) {
+ _finish_path(ctx);
- if (!ctx->pathPtr)//nothing to clip
- return;
+ if (!ctx->pathPtr) // nothing to clip
+ return;
- _emit_draw_cmd_undrawn_vertices(ctx);
+ _emit_draw_cmd_undrawn_vertices(ctx);
- LOG(VKVG_LOG_INFO, "CLIP: ctx = %p; path cpt = %d;\n", ctx, ctx->pathPtr / 2);
+ LOG(VKVG_LOG_INFO, "CLIP: ctx = %p; path cpt = %d;\n", ctx, ctx->pathPtr / 2);
- _ensure_renderpass_is_started(ctx);
+ _ensure_renderpass_is_started(ctx);
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_start(ctx->cmd, "clip", DBG_LAB_COLOR_CLIP);
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_start(ctx->cmd, "clip", DBG_LAB_COLOR_CLIP);
#endif
- if (ctx->curFillRule == VKVG_FILL_RULE_EVEN_ODD){
- _poly_fill (ctx, NULL);
- CmdBindPipeline (ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelineClipping);
- }else{
- CmdBindPipeline (ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelineClipping);
- CmdSetStencilReference (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT);
- CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
- CmdSetStencilWriteMask (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT);
- _fill_non_zero(ctx);
- _emit_draw_cmd_undrawn_vertices(ctx);
- }
- CmdSetStencilReference (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
- CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT);
- CmdSetStencilWriteMask (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_ALL_BIT);
-
- _draw_full_screen_quad (ctx, NULL);
-
- _bind_draw_pipeline (ctx);
- CmdSetStencilCompareMask (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
-
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_end (ctx->cmd);
+ if (ctx->curFillRule == VKVG_FILL_RULE_EVEN_ODD) {
+ _poly_fill(ctx, NULL);
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelineClipping);
+ } else {
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelineClipping);
+ CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT);
+ CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
+ CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT);
+ _fill_non_zero(ctx);
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ }
+ CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
+ CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT);
+ CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_ALL_BIT);
+
+ _draw_full_screen_quad(ctx, NULL);
+
+ _bind_draw_pipeline(ctx);
+ CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_end(ctx->cmd);
#endif
- ctx->curClipState = vkvg_clip_state_clip;
-}
-void _fill_preserve (VkvgContext ctx){
- _finish_path(ctx);
-
- if (!ctx->pathPtr)//nothing to fill
- return;
-
- LOG(VKVG_LOG_INFO, "FILL: ctx = %p; path cpt = %d;\n", ctx, ctx->subpathCount);
-
- if (ctx->curFillRule == VKVG_FILL_RULE_EVEN_ODD){
- _emit_draw_cmd_undrawn_vertices(ctx);
- vec4 bounds = {FLT_MAX,FLT_MAX,FLT_MIN,FLT_MIN};
- _poly_fill (ctx, &bounds);
- _bind_draw_pipeline (ctx);
- CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT);
- _draw_full_screen_quad (ctx, &bounds);
- CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
- return;
- }
-
- if (ctx->vertCount - ctx->curVertOffset + ctx->pointCount > VKVG_IBO_MAX)
- _emit_draw_cmd_undrawn_vertices(ctx);//limit draw call to addressable vx with choosen index type
-
- if (ctx->pattern)//if not solid color, source img or gradient has to be bound
- _ensure_renderpass_is_started(ctx);
- _fill_non_zero(ctx);
-}
-void _stroke_preserve (VkvgContext ctx)
-{
- _finish_path(ctx);
-
- if (!ctx->pathPtr)//nothing to stroke
- return;
-
- LOG(VKVG_LOG_INFO, "STROKE: ctx = %p; path ptr = %d;\n", ctx, ctx->pathPtr);
-
- stroke_context_t str = {0};
- str.hw = ctx->lineWidth * 0.5f;
- str.lhMax = ctx->miterLimit * ctx->lineWidth;
- uint32_t ptrPath = 0;
-
- while (ptrPath < ctx->pathPtr){
- uint32_t ptrSegment = 0, lastSegmentPointIdx = 0;
- uint32_t firstPathPointIdx = str.cp;
- uint32_t pathPointCount = ctx->pathes[ptrPath]&PATH_ELT_MASK;
- uint32_t lastPathPointIdx = str.cp + pathPointCount - 1;
-
- dash_context_t dc = {0};
-
- if (_path_has_curves (ctx,ptrPath)) {
- ptrSegment = 1;
- lastSegmentPointIdx = str.cp + (ctx->pathes[ptrPath+ptrSegment]&PATH_ELT_MASK)-1;
- }
-
- str.firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
-
- //LOG(VKVG_LOG_INFO_PATH, "\tPATH: points count=%10d end point idx=%10d", ctx->pathes[ptrPath]&PATH_ELT_MASK, lastPathPointIdx);
-
- if (ctx->dashCount > 0) {
- //init dash stroke
- dc.dashOn = true;
- dc.curDash = 0; //current dash index
- dc.totDashLength = 0;//limit offset to total length of dashes
- for (uint32_t i=0;i<ctx->dashCount;i++)
- dc.totDashLength += ctx->dashes[i];
- if (dc.totDashLength == 0){
- ctx->status = VKVG_STATUS_INVALID_DASH;
- return;
- }
- dc.curDashOffset = fmodf(ctx->dashOffset, dc.totDashLength); //cur dash offset between defined path point and last dash segment(on/off) start
- str.iL = lastPathPointIdx;
- } else if (_path_is_closed(ctx,ptrPath)){
- str.iL = lastPathPointIdx;
- }else{
- _draw_stoke_cap(ctx, &str, ctx->points[str.cp], vec2_line_norm(ctx->points[str.cp], ctx->points[str.cp+1]), true);
- str.iL = str.cp++;
- }
-
- if (_path_has_curves (ctx,ptrPath)) {
- while (str.cp < lastPathPointIdx){
-
- bool curved = ctx->pathes [ptrPath + ptrSegment] & PATH_HAS_CURVES_BIT;
- if (lastSegmentPointIdx == lastPathPointIdx)//last segment of path, dont draw end point here
- lastSegmentPointIdx--;
- while (str.cp <= lastSegmentPointIdx)
- _draw_segment(ctx, &str, &dc, curved);
-
- ptrSegment ++;
- uint32_t cptSegPts = ctx->pathes [ptrPath + ptrSegment]&PATH_ELT_MASK;
- lastSegmentPointIdx = str.cp + cptSegPts - 1;
- if (lastSegmentPointIdx == lastPathPointIdx && cptSegPts == 1) {
- //single point last segment
- ptrSegment++;
- break;
- }
- }
- }else while (str.cp < lastPathPointIdx)
- _draw_segment(ctx, &str, &dc, false);
-
- if (ctx->dashCount > 0) {
- if (_path_is_closed(ctx,ptrPath)){
- str.iR = firstPathPointIdx;
-
- _draw_dashed_segment(ctx, &str, &dc, false);
-
- str.iL++;
- str.cp++;
- }
- if (!dc.dashOn){
- //finishing last dash that is already started, draw end caps but not too close to start
- //the default gap is the next void
- int32_t prevDash = (int32_t)dc.curDash-1;
- if (prevDash < 0)
- dc.curDash = ctx->dashCount-1;
- float m = fminf (ctx->dashes[prevDash] - dc.curDashOffset, ctx->dashes[dc.curDash]);
- vec2 p = vec2_sub(ctx->points[str.iR], vec2_mult_s(dc.normal, m));
- _draw_stoke_cap (ctx, &str, p, dc.normal, false);
- }
- } else if (_path_is_closed(ctx,ptrPath)){
- str.iR = firstPathPointIdx;
- bool inverse = _build_vb_step (ctx, &str, false);
-
- VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache [ctx->indCount-6];
- VKVG_IBO_INDEX_TYPE ii = str.firstIdx;
- if (inverse){
- inds[1] = ii+1;
- inds[4] = ii+1;
- inds[5] = ii;
- }else{
- inds[1] = ii;
- inds[4] = ii;
- inds[5] = ii+1;
- }
- str.cp++;
- }else
- _draw_stoke_cap (ctx, &str, ctx->points[str.cp], vec2_line_norm(ctx->points[str.cp-1], ctx->points[str.cp]), false);
-
- str.cp = firstPathPointIdx + pathPointCount;
-
- if (ptrSegment > 0)
- ptrPath += ptrSegment;
- else
- ptrPath++;
-
- //limit batch size here to 1/3 of the ibo index type ability
- if (ctx->vertCount - ctx->curVertOffset > VKVG_IBO_MAX / 3)
- _emit_draw_cmd_undrawn_vertices (ctx);
- }
-
-}
-
-void vkvg_clip (VkvgContext ctx){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_CLIP);
- _clip_preserve(ctx);
- _clear_path(ctx);
-}
-void vkvg_stroke (VkvgContext ctx)
-{
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_STROKE);
- _stroke_preserve(ctx);
- _clear_path(ctx);
-}
-void vkvg_fill (VkvgContext ctx){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_FILL);
- _fill_preserve(ctx);
- _clear_path(ctx);
-}
-void vkvg_clip_preserve (VkvgContext ctx) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_CLIP_PRESERVE);
- _clip_preserve (ctx);
-}
-void vkvg_fill_preserve (VkvgContext ctx) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_FILL_PRESERVE);
- _fill_preserve (ctx);
-}
-void vkvg_stroke_preserve (VkvgContext ctx) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_STROKE_PRESERVE);
- _stroke_preserve (ctx);
-}
-
-void vkvg_paint (VkvgContext ctx){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_PAINT);
- _finish_path (ctx);
-
- if (ctx->pathPtr) {
- vkvg_fill(ctx);
- return;
- }
-
- _ensure_renderpass_is_started (ctx);
- _draw_full_screen_quad (ctx, NULL);
-}
-void vkvg_set_source_color (VkvgContext ctx, uint32_t c) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_SOURCE_COLOR, c);
- ctx->curColor = c;
- _update_cur_pattern (ctx, NULL);
-}
-void vkvg_set_source_rgb (VkvgContext ctx, float r, float g, float b) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_SOURCE_RGB, r, g, b);
- ctx->curColor = CreateRgbaf(r,g,b,1);
- _update_cur_pattern (ctx, NULL);
-}
-void vkvg_set_source_rgba (VkvgContext ctx, float r, float g, float b, float a)
-{
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_SOURCE_RGBA, r, g, b, a);
- ctx->curColor = CreateRgbaf(r,g,b,a);
- _update_cur_pattern (ctx, NULL);
-}
-void vkvg_set_source_surface(VkvgContext ctx, VkvgSurface surf, float x, float y){
- if (ctx->status || surf->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_SOURCE_SURFACE, x, y, surf);
- ctx->pushConsts.source.x = x;
- ctx->pushConsts.source.y = y;
- _update_cur_pattern (ctx, vkvg_pattern_create_for_surface(surf));
- ctx->pushCstDirty = true;
-}
-void vkvg_set_source (VkvgContext ctx, VkvgPattern pat){
- if (ctx->status || pat->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_SOURCE, pat);
- _update_cur_pattern (ctx, pat);
- vkvg_pattern_reference (pat);
-}
-void vkvg_set_line_width (VkvgContext ctx, float width){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_LINE_WIDTH, width);
- ctx->lineWidth = width;
-}
-void vkvg_set_miter_limit (VkvgContext ctx, float limit){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_LINE_WIDTH, limit);
- ctx->miterLimit = limit;
-}
-void vkvg_set_line_cap (VkvgContext ctx, vkvg_line_cap_t cap){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_LINE_CAP, cap);
- ctx->lineCap = cap;
-}
-void vkvg_set_line_join (VkvgContext ctx, vkvg_line_join_t join){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_LINE_JOIN, join);
- ctx->lineJoin = join;
-}
-void vkvg_set_operator (VkvgContext ctx, vkvg_operator_t op){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_OPERATOR, op);
- if (op == ctx->curOperator)
- return;
-
- _emit_draw_cmd_undrawn_vertices(ctx);//draw call with different ops cant be combined, so emit draw cmd for previous vertices.
-
- ctx->curOperator = op;
-
- if (ctx->cmdStarted)
- _bind_draw_pipeline (ctx);
-}
-void vkvg_set_fill_rule (VkvgContext ctx, vkvg_fill_rule_t fr){
- if (ctx->status)
- return;
+ ctx->curClipState = vkvg_clip_state_clip;
+}
+void _fill_preserve(VkvgContext ctx) {
+ _finish_path(ctx);
+
+ if (!ctx->pathPtr) // nothing to fill
+ return;
+
+ LOG(VKVG_LOG_INFO, "FILL: ctx = %p; path cpt = %d;\n", ctx, ctx->subpathCount);
+
+ if (ctx->curFillRule == VKVG_FILL_RULE_EVEN_ODD) {
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ vec4 bounds = {FLT_MAX, FLT_MAX, FLT_MIN, FLT_MIN};
+ _poly_fill(ctx, &bounds);
+ _bind_draw_pipeline(ctx);
+ CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT);
+ _draw_full_screen_quad(ctx, &bounds);
+ CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
+ return;
+ }
+
+ if (ctx->vertCount - ctx->curVertOffset + ctx->pointCount > VKVG_IBO_MAX)
+ _emit_draw_cmd_undrawn_vertices(ctx); // limit draw call to addressable vx with choosen index type
+
+ if (ctx->pattern) // if not solid color, source img or gradient has to be bound
+ _ensure_renderpass_is_started(ctx);
+ _fill_non_zero(ctx);
+}
+void _stroke_preserve(VkvgContext ctx) {
+ _finish_path(ctx);
+
+ if (!ctx->pathPtr) // nothing to stroke
+ return;
+
+ LOG(VKVG_LOG_INFO, "STROKE: ctx = %p; path ptr = %d;\n", ctx, ctx->pathPtr);
+
+ stroke_context_t str = {0};
+ str.hw = ctx->lineWidth * 0.5f;
+ str.lhMax = ctx->miterLimit * ctx->lineWidth;
+ uint32_t ptrPath = 0;
+
+ while (ptrPath < ctx->pathPtr) {
+ uint32_t ptrSegment = 0, lastSegmentPointIdx = 0;
+ uint32_t firstPathPointIdx = str.cp;
+ uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+ uint32_t lastPathPointIdx = str.cp + pathPointCount - 1;
+
+ dash_context_t dc = {0};
+
+ if (_path_has_curves(ctx, ptrPath)) {
+ ptrSegment = 1;
+ lastSegmentPointIdx = str.cp + (ctx->pathes[ptrPath + ptrSegment] & PATH_ELT_MASK) - 1;
+ }
+
+ str.firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+
+ // LOG(VKVG_LOG_INFO_PATH, "\tPATH: points count=%10d end point idx=%10d", ctx->pathes[ptrPath]&PATH_ELT_MASK,
+ // lastPathPointIdx);
+
+ if (ctx->dashCount > 0) {
+ // init dash stroke
+ dc.dashOn = true;
+ dc.curDash = 0; // current dash index
+ dc.totDashLength = 0; // limit offset to total length of dashes
+ for (uint32_t i = 0; i < ctx->dashCount; i++)
+ dc.totDashLength += ctx->dashes[i];
+ if (dc.totDashLength == 0) {
+ ctx->status = VKVG_STATUS_INVALID_DASH;
+ return;
+ }
+ dc.curDashOffset = fmodf(
+ ctx->dashOffset,
+ dc.totDashLength); // cur dash offset between defined path point and last dash segment(on/off) start
+ str.iL = lastPathPointIdx;
+ } else if (_path_is_closed(ctx, ptrPath)) {
+ str.iL = lastPathPointIdx;
+ } else {
+ _draw_stoke_cap(ctx, &str, ctx->points[str.cp],
+ vec2_line_norm(ctx->points[str.cp], ctx->points[str.cp + 1]), true);
+ str.iL = str.cp++;
+ }
+
+ if (_path_has_curves(ctx, ptrPath)) {
+ while (str.cp < lastPathPointIdx) {
+
+ bool curved = ctx->pathes[ptrPath + ptrSegment] & PATH_HAS_CURVES_BIT;
+ if (lastSegmentPointIdx == lastPathPointIdx) // last segment of path, dont draw end point here
+ lastSegmentPointIdx--;
+ while (str.cp <= lastSegmentPointIdx)
+ _draw_segment(ctx, &str, &dc, curved);
+
+ ptrSegment++;
+ uint32_t cptSegPts = ctx->pathes[ptrPath + ptrSegment] & PATH_ELT_MASK;
+ lastSegmentPointIdx = str.cp + cptSegPts - 1;
+ if (lastSegmentPointIdx == lastPathPointIdx && cptSegPts == 1) {
+ // single point last segment
+ ptrSegment++;
+ break;
+ }
+ }
+ } else
+ while (str.cp < lastPathPointIdx)
+ _draw_segment(ctx, &str, &dc, false);
+
+ if (ctx->dashCount > 0) {
+ if (_path_is_closed(ctx, ptrPath)) {
+ str.iR = firstPathPointIdx;
+
+ _draw_dashed_segment(ctx, &str, &dc, false);
+
+ str.iL++;
+ str.cp++;
+ }
+ if (!dc.dashOn) {
+ // finishing last dash that is already started, draw end caps but not too close to start
+ // the default gap is the next void
+ int32_t prevDash = (int32_t)dc.curDash - 1;
+ if (prevDash < 0)
+ dc.curDash = ctx->dashCount - 1;
+ float m = fminf(ctx->dashes[prevDash] - dc.curDashOffset, ctx->dashes[dc.curDash]);
+ vec2 p = vec2_sub(ctx->points[str.iR], vec2_mult_s(dc.normal, m));
+ _draw_stoke_cap(ctx, &str, p, dc.normal, false);
+ }
+ } else if (_path_is_closed(ctx, ptrPath)) {
+ str.iR = firstPathPointIdx;
+ bool inverse = _build_vb_step(ctx, &str, false);
+
+ VKVG_IBO_INDEX_TYPE *inds = &ctx->indexCache[ctx->indCount - 6];
+ VKVG_IBO_INDEX_TYPE ii = str.firstIdx;
+ if (inverse) {
+ inds[1] = ii + 1;
+ inds[4] = ii + 1;
+ inds[5] = ii;
+ } else {
+ inds[1] = ii;
+ inds[4] = ii;
+ inds[5] = ii + 1;
+ }
+ str.cp++;
+ } else
+ _draw_stoke_cap(ctx, &str, ctx->points[str.cp],
+ vec2_line_norm(ctx->points[str.cp - 1], ctx->points[str.cp]), false);
+
+ str.cp = firstPathPointIdx + pathPointCount;
+
+ if (ptrSegment > 0)
+ ptrPath += ptrSegment;
+ else
+ ptrPath++;
+
+ // limit batch size here to 1/3 of the ibo index type ability
+ if (ctx->vertCount - ctx->curVertOffset > VKVG_IBO_MAX / 3)
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ }
+}
+
+void vkvg_clip(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_CLIP);
+ _clip_preserve(ctx);
+ _clear_path(ctx);
+}
+void vkvg_stroke(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_STROKE);
+ _stroke_preserve(ctx);
+ _clear_path(ctx);
+}
+void vkvg_fill(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_FILL);
+ _fill_preserve(ctx);
+ _clear_path(ctx);
+}
+void vkvg_clip_preserve(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_CLIP_PRESERVE);
+ _clip_preserve(ctx);
+}
+void vkvg_fill_preserve(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_FILL_PRESERVE);
+ _fill_preserve(ctx);
+}
+void vkvg_stroke_preserve(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_STROKE_PRESERVE);
+ _stroke_preserve(ctx);
+}
+
+void vkvg_paint(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_PAINT);
+ _finish_path(ctx);
+
+ if (ctx->pathPtr) {
+ vkvg_fill(ctx);
+ return;
+ }
+
+ _ensure_renderpass_is_started(ctx);
+ _draw_full_screen_quad(ctx, NULL);
+}
+void vkvg_set_source_color(VkvgContext ctx, uint32_t c) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_SOURCE_COLOR, c);
+ ctx->curColor = c;
+ _update_cur_pattern(ctx, NULL);
+}
+void vkvg_set_source_rgb(VkvgContext ctx, float r, float g, float b) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_SOURCE_RGB, r, g, b);
+ ctx->curColor = CreateRgbaf(r, g, b, 1);
+ _update_cur_pattern(ctx, NULL);
+}
+void vkvg_set_source_rgba(VkvgContext ctx, float r, float g, float b, float a) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_SOURCE_RGBA, r, g, b, a);
+ ctx->curColor = CreateRgbaf(r, g, b, a);
+ _update_cur_pattern(ctx, NULL);
+}
+void vkvg_set_source_surface(VkvgContext ctx, VkvgSurface surf, float x, float y) {
+ if (ctx->status || surf->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_SOURCE_SURFACE, x, y, surf);
+ ctx->pushConsts.source.x = x;
+ ctx->pushConsts.source.y = y;
+ _update_cur_pattern(ctx, vkvg_pattern_create_for_surface(surf));
+ ctx->pushCstDirty = true;
+}
+void vkvg_set_source(VkvgContext ctx, VkvgPattern pat) {
+ if (ctx->status || pat->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_SOURCE, pat);
+ _update_cur_pattern(ctx, pat);
+ vkvg_pattern_reference(pat);
+}
+void vkvg_set_line_width(VkvgContext ctx, float width) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_LINE_WIDTH, width);
+ ctx->lineWidth = width;
+}
+void vkvg_set_miter_limit(VkvgContext ctx, float limit) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_LINE_WIDTH, limit);
+ ctx->miterLimit = limit;
+}
+void vkvg_set_line_cap(VkvgContext ctx, vkvg_line_cap_t cap) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_LINE_CAP, cap);
+ ctx->lineCap = cap;
+}
+void vkvg_set_line_join(VkvgContext ctx, vkvg_line_join_t join) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_LINE_JOIN, join);
+ ctx->lineJoin = join;
+}
+void vkvg_set_operator(VkvgContext ctx, vkvg_operator_t op) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_OPERATOR, op);
+ if (op == ctx->curOperator)
+ return;
+
+ _emit_draw_cmd_undrawn_vertices(
+ ctx); // draw call with different ops cant be combined, so emit draw cmd for previous vertices.
+
+ ctx->curOperator = op;
+
+ if (ctx->cmdStarted)
+ _bind_draw_pipeline(ctx);
+}
+void vkvg_set_fill_rule(VkvgContext ctx, vkvg_fill_rule_t fr) {
+ if (ctx->status)
+ return;
#ifndef __APPLE__
- RECORD(ctx, VKVG_CMD_SET_FILL_RULE, fr);
- ctx->curFillRule = fr;
+ RECORD(ctx, VKVG_CMD_SET_FILL_RULE, fr);
+ ctx->curFillRule = fr;
#endif
}
-vkvg_fill_rule_t vkvg_get_fill_rule (VkvgContext ctx){
- if (ctx->status)
- return VKVG_FILL_RULE_NON_ZERO;
- return ctx->curFillRule;
-}
-float vkvg_get_line_width (VkvgContext ctx){
- if (ctx->status)
- return 0;
- return ctx->lineWidth;
-}
-void vkvg_set_dash (VkvgContext ctx, const float* dashes, uint32_t num_dashes, float offset){
- if (ctx->status)
- return;
- if (ctx->dashCount > 0)
- free (ctx->dashes);
- RECORD(ctx, VKVG_CMD_SET_DASH, num_dashes, offset, dashes);
- ctx->dashCount = num_dashes;
- ctx->dashOffset = offset;
- if (ctx->dashCount == 0)
- return;
- ctx->dashes = (float*)malloc (sizeof(float) * ctx->dashCount);
- memcpy (ctx->dashes, dashes, sizeof(float) * ctx->dashCount);
-}
-void vkvg_get_dash (VkvgContext ctx, const float* dashes, uint32_t* num_dashes, float* offset){
- if (ctx->status)
- return;
- *num_dashes = ctx->dashCount;
- *offset = ctx->dashOffset;
- if (ctx->dashCount == 0 || dashes == NULL)
- return;
- memcpy ((float*)dashes, ctx->dashes, sizeof(float) * ctx->dashCount);
-}
-
-
-vkvg_line_cap_t vkvg_get_line_cap (VkvgContext ctx){
- if (ctx->status)
- return (vkvg_line_cap_t)0;
- return ctx->lineCap;
-}
-vkvg_line_join_t vkvg_get_line_join (VkvgContext ctx){
- if (ctx->status)
- return (vkvg_line_join_t)0;
- return ctx->lineJoin;
-}
-vkvg_operator_t vkvg_get_operator (VkvgContext ctx){
- if (ctx->status)
- return (vkvg_operator_t)0;
- return ctx->curOperator;
-}
-VkvgPattern vkvg_get_source (VkvgContext ctx){
- if (ctx->status)
- return NULL;
- vkvg_pattern_reference (ctx->pattern);
- return ctx->pattern;
-}
-
-void vkvg_select_font_face (VkvgContext ctx, const char* name){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_FONT_FACE, name);
- _select_font_face (ctx, name);
-}
-void vkvg_load_font_from_path (VkvgContext ctx, const char* path, const char* name){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_FONT_PATH, name);
- _vkvg_font_identity_t* fid = _font_cache_add_font_identity(ctx, path, name);
- if (!_font_cache_load_font_file_in_memory (fid)) {
- ctx->status = VKVG_STATUS_FILE_NOT_FOUND;
- return;
- }
- _select_font_face (ctx, name);
-}
-void vkvg_load_font_from_memory (VkvgContext ctx, unsigned char* fontBuffer, long fontBufferByteSize, const char* name) {
- if (ctx->status)
- return;
- //RECORD(ctx, VKVG_CMD_SET_FONT_PATH, name);
- _vkvg_font_identity_t* fid = _font_cache_add_font_identity (ctx, NULL, name);
- fid->fontBuffer = fontBuffer;
- fid->fontBufSize = fontBufferByteSize;
-
- _select_font_face (ctx, name);
-}
-void vkvg_set_font_size (VkvgContext ctx, uint32_t size){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_FONT_SIZE, size);
+vkvg_fill_rule_t vkvg_get_fill_rule(VkvgContext ctx) {
+ if (ctx->status)
+ return VKVG_FILL_RULE_NON_ZERO;
+ return ctx->curFillRule;
+}
+float vkvg_get_line_width(VkvgContext ctx) {
+ if (ctx->status)
+ return 0;
+ return ctx->lineWidth;
+}
+void vkvg_set_dash(VkvgContext ctx, const float *dashes, uint32_t num_dashes, float offset) {
+ if (ctx->status)
+ return;
+ if (ctx->dashCount > 0)
+ free(ctx->dashes);
+ RECORD(ctx, VKVG_CMD_SET_DASH, num_dashes, offset, dashes);
+ ctx->dashCount = num_dashes;
+ ctx->dashOffset = offset;
+ if (ctx->dashCount == 0)
+ return;
+ ctx->dashes = (float *)malloc(sizeof(float) * ctx->dashCount);
+ memcpy(ctx->dashes, dashes, sizeof(float) * ctx->dashCount);
+}
+void vkvg_get_dash(VkvgContext ctx, const float *dashes, uint32_t *num_dashes, float *offset) {
+ if (ctx->status)
+ return;
+ *num_dashes = ctx->dashCount;
+ *offset = ctx->dashOffset;
+ if (ctx->dashCount == 0 || dashes == NULL)
+ return;
+ memcpy((float *)dashes, ctx->dashes, sizeof(float) * ctx->dashCount);
+}
+
+vkvg_line_cap_t vkvg_get_line_cap(VkvgContext ctx) {
+ if (ctx->status)
+ return (vkvg_line_cap_t)0;
+ return ctx->lineCap;
+}
+vkvg_line_join_t vkvg_get_line_join(VkvgContext ctx) {
+ if (ctx->status)
+ return (vkvg_line_join_t)0;
+ return ctx->lineJoin;
+}
+vkvg_operator_t vkvg_get_operator(VkvgContext ctx) {
+ if (ctx->status)
+ return (vkvg_operator_t)0;
+ return ctx->curOperator;
+}
+VkvgPattern vkvg_get_source(VkvgContext ctx) {
+ if (ctx->status)
+ return NULL;
+ vkvg_pattern_reference(ctx->pattern);
+ return ctx->pattern;
+}
+
+void vkvg_select_font_face(VkvgContext ctx, const char *name) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_FONT_FACE, name);
+ _select_font_face(ctx, name);
+}
+void vkvg_load_font_from_path(VkvgContext ctx, const char *path, const char *name) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_FONT_PATH, name);
+ _vkvg_font_identity_t *fid = _font_cache_add_font_identity(ctx, path, name);
+ if (!_font_cache_load_font_file_in_memory(fid)) {
+ ctx->status = VKVG_STATUS_FILE_NOT_FOUND;
+ return;
+ }
+ _select_font_face(ctx, name);
+}
+void vkvg_load_font_from_memory(VkvgContext ctx, unsigned char *fontBuffer, long fontBufferByteSize, const char *name) {
+ if (ctx->status)
+ return;
+ // RECORD(ctx, VKVG_CMD_SET_FONT_PATH, name);
+ _vkvg_font_identity_t *fid = _font_cache_add_font_identity(ctx, NULL, name);
+ fid->fontBuffer = fontBuffer;
+ fid->fontBufSize = fontBufferByteSize;
+
+ _select_font_face(ctx, name);
+}
+void vkvg_set_font_size(VkvgContext ctx, uint32_t size) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_FONT_SIZE, size);
#ifdef VKVG_USE_FREETYPE
- long newSize = size << 6;
+ long newSize = size << 6;
#else
- long newSize = size;
+ long newSize = size;
#endif
- if (ctx->selectedCharSize == newSize)
- return;
- ctx->selectedCharSize = newSize;
- ctx->currentFont = NULL;
- ctx->currentFontSize = NULL;
-}
-
-void vkvg_set_text_direction (vkvg_context* ctx, vkvg_direction_t direction){
-
-}
-
-void vkvg_show_text (VkvgContext ctx, const char* text){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SHOW_TEXT, text);
- LOG(VKVG_LOG_INFO_CMD, "CMD: show_text:\n");
- //_ensure_renderpass_is_started(ctx);
- _font_cache_show_text (ctx, text);
- //_flush_undrawn_vertices (ctx);
-}
-
-VkvgText vkvg_text_run_create (VkvgContext ctx, const char* text) {
- if (ctx->status)
- return NULL;
- VkvgText tr = (vkvg_text_run_t*)calloc(1, sizeof(vkvg_text_run_t));
- _font_cache_create_text_run(ctx, text, -1, tr);
- return tr;
-}
-VkvgText vkvg_text_run_create_with_length (VkvgContext ctx, const char* text, uint32_t length) {
- if (ctx->status)
- return NULL;
- VkvgText tr = (vkvg_text_run_t*)calloc(1, sizeof(vkvg_text_run_t));
- _font_cache_create_text_run(ctx, text, length, tr);
- return tr;
-}
-uint32_t vkvg_text_run_get_glyph_count (VkvgText textRun) {
- return textRun->glyph_count;
-}
-void vkvg_text_run_get_glyph_position (VkvgText textRun,
- uint32_t index,
- vkvg_glyph_info_t* pGlyphInfo) {
- if (index >= textRun->glyph_count) {
- *pGlyphInfo = (vkvg_glyph_info_t){0};
- return;
- }
+ if (ctx->selectedCharSize == newSize)
+ return;
+ ctx->selectedCharSize = newSize;
+ ctx->currentFont = NULL;
+ ctx->currentFontSize = NULL;
+}
+
+void vkvg_set_text_direction(vkvg_context *ctx, vkvg_direction_t direction) {}
+
+void vkvg_show_text(VkvgContext ctx, const char *text) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SHOW_TEXT, text);
+ LOG(VKVG_LOG_INFO_CMD, "CMD: show_text:\n");
+ //_ensure_renderpass_is_started(ctx);
+ _font_cache_show_text(ctx, text);
+ //_flush_undrawn_vertices (ctx);
+}
+
+VkvgText vkvg_text_run_create(VkvgContext ctx, const char *text) {
+ if (ctx->status)
+ return NULL;
+ VkvgText tr = (vkvg_text_run_t *)calloc(1, sizeof(vkvg_text_run_t));
+ _font_cache_create_text_run(ctx, text, -1, tr);
+ return tr;
+}
+VkvgText vkvg_text_run_create_with_length(VkvgContext ctx, const char *text, uint32_t length) {
+ if (ctx->status)
+ return NULL;
+ VkvgText tr = (vkvg_text_run_t *)calloc(1, sizeof(vkvg_text_run_t));
+ _font_cache_create_text_run(ctx, text, length, tr);
+ return tr;
+}
+uint32_t vkvg_text_run_get_glyph_count(VkvgText textRun) { return textRun->glyph_count; }
+void vkvg_text_run_get_glyph_position(VkvgText textRun, uint32_t index, vkvg_glyph_info_t *pGlyphInfo) {
+ if (index >= textRun->glyph_count) {
+ *pGlyphInfo = (vkvg_glyph_info_t){0};
+ return;
+ }
#if VKVG_USE_HARFBUZZ
- memcpy (pGlyphInfo, &textRun->glyphs[index], sizeof(vkvg_glyph_info_t));
+ memcpy(pGlyphInfo, &textRun->glyphs[index], sizeof(vkvg_glyph_info_t));
#else
- *pGlyphInfo = textRun->glyphs[index];
+ *pGlyphInfo = textRun->glyphs[index];
#endif
}
-void vkvg_text_run_destroy (VkvgText textRun) {
- _font_cache_destroy_text_run (textRun);
- free (textRun);
-}
-void vkvg_show_text_run (VkvgContext ctx, VkvgText textRun) {
- if (ctx->status)
- return;
- _font_cache_show_text_run(ctx, textRun);
-}
-void vkvg_text_run_get_extents (VkvgText textRun, vkvg_text_extents_t* extents) {
- *extents = textRun->extents;
-}
-
-void vkvg_text_extents (VkvgContext ctx, const char* text, vkvg_text_extents_t* extents) {
- if (ctx->status)
- return;
- _font_cache_text_extents(ctx, text, -1, extents);
-}
-void vkvg_font_extents (VkvgContext ctx, vkvg_font_extents_t* extents) {
- if (ctx->status)
- return;
- _font_cache_font_extents(ctx, extents);
-}
-
-void vkvg_save (VkvgContext ctx){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SAVE);
- LOG(VKVG_LOG_INFO, "SAVE CONTEXT: ctx = %p\n", ctx);
-
- VkvgDevice dev = ctx->dev;
- vkvg_context_save_t* sav = (vkvg_context_save_t*)calloc(1,sizeof(vkvg_context_save_t));
-
- _flush_cmd_buff (ctx);
- if (!_wait_ctx_flush_end (ctx)) {
- free (sav);
- return;
- }
-
- if (ctx->curClipState == vkvg_clip_state_clip) {
- sav->clippingState = vkvg_clip_state_clip_saved;
-
- uint8_t curSaveStencil = ctx->curSavBit / 6;
-
- if (ctx->curSavBit > 0 && ctx->curSavBit % 6 == 0){//new save/restore stencil image have to be created
- VkhImage* savedStencilsPtr = NULL;
- if (savedStencilsPtr)
- savedStencilsPtr = (VkhImage*)realloc(ctx->savedStencils, curSaveStencil * sizeof(VkhImage));
- else
- savedStencilsPtr = (VkhImage*)malloc(curSaveStencil * sizeof(VkhImage));
- if (savedStencilsPtr == NULL) {
- free(sav);
- ctx->status = VKVG_STATUS_NO_MEMORY;
- return;
- }
- ctx->savedStencils = savedStencilsPtr;
- VkhImage savStencil = vkh_image_ms_create ((VkhDevice)dev, dev->stencilFormat, dev->samples, ctx->pSurf->width, ctx->pSurf->height,
- VKH_MEMORY_USAGE_GPU_ONLY, VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT);
- ctx->savedStencils[curSaveStencil-1] = savStencil;
-
- vkh_cmd_begin (ctx->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- ctx->cmdStarted = true;
-
- #if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_start(ctx->cmd, "new save/restore stencil", DBG_LAB_COLOR_SAV);
- #endif
-
- vkh_image_set_layout (ctx->cmd, ctx->pSurf->stencil, dev->stencilAspectFlag,
- VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkh_image_set_layout (ctx->cmd, savStencil, dev->stencilAspectFlag,
- VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
-
- VkImageCopy cregion = { .srcSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
- .dstSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
- .extent = {ctx->pSurf->width,ctx->pSurf->height,1}};
- vkCmdCopyImage(ctx->cmd,
- vkh_image_get_vkimage (ctx->pSurf->stencil),VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- vkh_image_get_vkimage (savStencil), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1, &cregion);
-
- vkh_image_set_layout (ctx->cmd, ctx->pSurf->stencil, dev->stencilAspectFlag,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
-
- #if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_end (ctx->cmd);
- #endif
-
- VK_CHECK_RESULT(vkEndCommandBuffer(ctx->cmd));
- _wait_and_submit_cmd(ctx);
- }
-
- uint8_t curSaveBit = 1 << (ctx->curSavBit % 6 + 2);
-
- _start_cmd_for_render_pass (ctx);
-
- #if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_start(ctx->cmd, "save rp", DBG_LAB_COLOR_SAV);
- #endif
-
- CmdBindPipeline (ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelineClipping);
-
- CmdSetStencilReference (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT|curSaveBit);
- CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
- CmdSetStencilWriteMask (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, curSaveBit);
-
- _draw_full_screen_quad (ctx, NULL);
-
- _bind_draw_pipeline (ctx);
- CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
-
- #if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_end (ctx->cmd);
- #endif
- ctx->curSavBit++;
- } else if (ctx->curClipState == vkvg_clip_state_none)
- sav->clippingState = (_get_previous_clip_state(ctx) & 0x03);
- else
- sav->clippingState = vkvg_clip_state_clear;
-
- sav->dashOffset = ctx->dashOffset;
- sav->dashCount = ctx->dashCount;
- if (ctx->dashCount > 0) {
- sav->dashes = (float*)malloc (sizeof(float) * ctx->dashCount);
- memcpy (sav->dashes, ctx->dashes, sizeof(float) * ctx->dashCount);
- }
- sav->lineWidth = ctx->lineWidth;
- sav->miterLimit = ctx->miterLimit;
- sav->curOperator= ctx->curOperator;
- sav->lineCap = ctx->lineCap;
- sav->lineWidth = ctx->lineWidth;
- sav->curFillRule= ctx->curFillRule;
-
- sav->selectedCharSize = ctx->selectedCharSize;
- strcpy (sav->selectedFontName, ctx->selectedFontName);
-
- sav->currentFont = ctx->currentFont;
- sav->textDirection= ctx->textDirection;
- sav->pushConsts = ctx->pushConsts;
- if (ctx->pattern) {
- sav->pattern = ctx->pattern;//TODO:pattern sav must be imutable (copy?)
- vkvg_pattern_reference (ctx->pattern);
- } else
- sav->curColor = ctx->curColor;
-
- sav->pNext = ctx->pSavedCtxs;
- ctx->pSavedCtxs = sav;
-
-}
-void vkvg_restore (VkvgContext ctx){
- if (ctx->status)
- return;
-
- RECORD(ctx, VKVG_CMD_RESTORE);
-
- if (ctx->pSavedCtxs == NULL){
- ctx->status = VKVG_STATUS_INVALID_RESTORE;
- return;
- }
-
- LOG(VKVG_LOG_INFO, "RESTORE CONTEXT: ctx = %p\n", ctx);
-
- vkvg_context_save_t* sav = ctx->pSavedCtxs;
- ctx->pSavedCtxs = sav->pNext;
-
- _flush_cmd_buff (ctx);
- if (!_wait_ctx_flush_end (ctx))
- return;
+void vkvg_text_run_destroy(VkvgText textRun) {
+ _font_cache_destroy_text_run(textRun);
+ free(textRun);
+}
+void vkvg_show_text_run(VkvgContext ctx, VkvgText textRun) {
+ if (ctx->status)
+ return;
+ _font_cache_show_text_run(ctx, textRun);
+}
+void vkvg_text_run_get_extents(VkvgText textRun, vkvg_text_extents_t *extents) { *extents = textRun->extents; }
+
+void vkvg_text_extents(VkvgContext ctx, const char *text, vkvg_text_extents_t *extents) {
+ if (ctx->status)
+ return;
+ _font_cache_text_extents(ctx, text, -1, extents);
+}
+void vkvg_font_extents(VkvgContext ctx, vkvg_font_extents_t *extents) {
+ if (ctx->status)
+ return;
+ _font_cache_font_extents(ctx, extents);
+}
+
+void vkvg_save(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SAVE);
+ LOG(VKVG_LOG_INFO, "SAVE CONTEXT: ctx = %p\n", ctx);
+
+ VkvgDevice dev = ctx->dev;
+ vkvg_context_save_t *sav = (vkvg_context_save_t *)calloc(1, sizeof(vkvg_context_save_t));
+
+ _flush_cmd_buff(ctx);
+ if (!_wait_ctx_flush_end(ctx)) {
+ free(sav);
+ return;
+ }
+
+ if (ctx->curClipState == vkvg_clip_state_clip) {
+ sav->clippingState = vkvg_clip_state_clip_saved;
+
+ uint8_t curSaveStencil = ctx->curSavBit / 6;
+
+ if (ctx->curSavBit > 0 && ctx->curSavBit % 6 == 0) { // new save/restore stencil image have to be created
+ VkhImage *savedStencilsPtr = NULL;
+ if (savedStencilsPtr)
+ savedStencilsPtr = (VkhImage *)realloc(ctx->savedStencils, curSaveStencil * sizeof(VkhImage));
+ else
+ savedStencilsPtr = (VkhImage *)malloc(curSaveStencil * sizeof(VkhImage));
+ if (savedStencilsPtr == NULL) {
+ free(sav);
+ ctx->status = VKVG_STATUS_NO_MEMORY;
+ return;
+ }
+ ctx->savedStencils = savedStencilsPtr;
+ VkhImage savStencil = vkh_image_ms_create(
+ (VkhDevice)dev, dev->stencilFormat, dev->samples, ctx->pSurf->width, ctx->pSurf->height,
+ VKH_MEMORY_USAGE_GPU_ONLY, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+ ctx->savedStencils[curSaveStencil - 1] = savStencil;
+
+ vkh_cmd_begin(ctx->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ ctx->cmdStarted = true;
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_start(ctx->cmd, "new save/restore stencil", DBG_LAB_COLOR_SAV);
+#endif
- ctx->pushConsts = sav->pushConsts;
- ctx->pushCstDirty = true;
+ vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, dev->stencilAspectFlag,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout(ctx->cmd, savStencil, dev->stencilAspectFlag, VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ VkImageCopy cregion = {.srcSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
+ .dstSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
+ .extent = {ctx->pSurf->width, ctx->pSurf->height, 1}};
+ vkCmdCopyImage(ctx->cmd, vkh_image_get_vkimage(ctx->pSurf->stencil), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vkh_image_get_vkimage(savStencil), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cregion);
+
+ vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, dev->stencilAspectFlag,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_end(ctx->cmd);
+#endif
- if (ctx->curClipState) {//!=none
- if (ctx->curClipState == vkvg_clip_state_clip && sav->clippingState == vkvg_clip_state_clear) {
- _reset_clip (ctx);
- } else {
+ VK_CHECK_RESULT(vkEndCommandBuffer(ctx->cmd));
+ _wait_and_submit_cmd(ctx);
+ }
- uint8_t curSaveBit = 1 << ((ctx->curSavBit-1) % 6 + 2);
+ uint8_t curSaveBit = 1 << (ctx->curSavBit % 6 + 2);
- _start_cmd_for_render_pass (ctx);
+ _start_cmd_for_render_pass(ctx);
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_start(ctx->cmd, "restore rp", DBG_LAB_COLOR_SAV);
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_start(ctx->cmd, "save rp", DBG_LAB_COLOR_SAV);
#endif
- CmdBindPipeline (ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelineClipping);
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelineClipping);
- CmdSetStencilReference (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT|curSaveBit);
- CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, curSaveBit);
- CmdSetStencilWriteMask (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
+ CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT | curSaveBit);
+ CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
+ CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, curSaveBit);
- _draw_full_screen_quad (ctx, NULL);
+ _draw_full_screen_quad(ctx, NULL);
- _bind_draw_pipeline (ctx);
- CmdSetStencilCompareMask (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
+ _bind_draw_pipeline(ctx);
+ CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_end (ctx->cmd);
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_end(ctx->cmd);
#endif
+ ctx->curSavBit++;
+ } else if (ctx->curClipState == vkvg_clip_state_none)
+ sav->clippingState = (_get_previous_clip_state(ctx) & 0x03);
+ else
+ sav->clippingState = vkvg_clip_state_clear;
+
+ sav->dashOffset = ctx->dashOffset;
+ sav->dashCount = ctx->dashCount;
+ if (ctx->dashCount > 0) {
+ sav->dashes = (float *)malloc(sizeof(float) * ctx->dashCount);
+ memcpy(sav->dashes, ctx->dashes, sizeof(float) * ctx->dashCount);
+ }
+ sav->lineWidth = ctx->lineWidth;
+ sav->miterLimit = ctx->miterLimit;
+ sav->curOperator = ctx->curOperator;
+ sav->lineCap = ctx->lineCap;
+ sav->lineWidth = ctx->lineWidth;
+ sav->curFillRule = ctx->curFillRule;
+
+ sav->selectedCharSize = ctx->selectedCharSize;
+ strcpy(sav->selectedFontName, ctx->selectedFontName);
+
+ sav->currentFont = ctx->currentFont;
+ sav->textDirection = ctx->textDirection;
+ sav->pushConsts = ctx->pushConsts;
+ if (ctx->pattern) {
+ sav->pattern = ctx->pattern; // TODO:pattern sav must be imutable (copy?)
+ vkvg_pattern_reference(ctx->pattern);
+ } else
+ sav->curColor = ctx->curColor;
+
+ sav->pNext = ctx->pSavedCtxs;
+ ctx->pSavedCtxs = sav;
+}
+void vkvg_restore(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+
+ RECORD(ctx, VKVG_CMD_RESTORE);
+
+ if (ctx->pSavedCtxs == NULL) {
+ ctx->status = VKVG_STATUS_INVALID_RESTORE;
+ return;
+ }
+
+ LOG(VKVG_LOG_INFO, "RESTORE CONTEXT: ctx = %p\n", ctx);
+
+ vkvg_context_save_t *sav = ctx->pSavedCtxs;
+ ctx->pSavedCtxs = sav->pNext;
+
+ _flush_cmd_buff(ctx);
+ if (!_wait_ctx_flush_end(ctx))
+ return;
+
+ ctx->pushConsts = sav->pushConsts;
+ ctx->pushCstDirty = true;
+
+ if (ctx->curClipState) { //!=none
+ if (ctx->curClipState == vkvg_clip_state_clip && sav->clippingState == vkvg_clip_state_clear) {
+ _reset_clip(ctx);
+ } else {
+
+ uint8_t curSaveBit = 1 << ((ctx->curSavBit - 1) % 6 + 2);
+
+ _start_cmd_for_render_pass(ctx);
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_start(ctx->cmd, "restore rp", DBG_LAB_COLOR_SAV);
+#endif
+
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelineClipping);
- _flush_cmd_buff (ctx);
- if (!_wait_ctx_flush_end (ctx))
- return;
- }
- }
- if (sav->clippingState == vkvg_clip_state_clip_saved) {
- ctx->curSavBit--;
+ CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT | curSaveBit);
+ CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, curSaveBit);
+ CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
- uint8_t curSaveStencil = ctx->curSavBit / 6;
- if (ctx->curSavBit > 0 && ctx->curSavBit % 6 == 0){//addtional save/restore stencil image have to be copied back to surf stencil first
- VkhImage savStencil = ctx->savedStencils[curSaveStencil-1];
+ _draw_full_screen_quad(ctx, NULL);
- vkh_cmd_begin (ctx->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- ctx->cmdStarted = true;
+ _bind_draw_pipeline(ctx);
+ CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_end(ctx->cmd);
+#endif
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_start(ctx->cmd, "additional stencil copy while restoring", DBG_LAB_COLOR_SAV);
+ _flush_cmd_buff(ctx);
+ if (!_wait_ctx_flush_end(ctx))
+ return;
+ }
+ }
+ if (sav->clippingState == vkvg_clip_state_clip_saved) {
+ ctx->curSavBit--;
+
+ uint8_t curSaveStencil = ctx->curSavBit / 6;
+ if (ctx->curSavBit > 0 &&
+ ctx->curSavBit % 6 ==
+ 0) { // addtional save/restore stencil image have to be copied back to surf stencil first
+ VkhImage savStencil = ctx->savedStencils[curSaveStencil - 1];
+
+ vkh_cmd_begin(ctx->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ ctx->cmdStarted = true;
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_start(ctx->cmd, "additional stencil copy while restoring", DBG_LAB_COLOR_SAV);
#endif
- vkh_image_set_layout (ctx->cmd, ctx->pSurf->stencil, ctx->dev->stencilAspectFlag,
- VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkh_image_set_layout (ctx->cmd, savStencil, ctx->dev->stencilAspectFlag,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
-
- VkImageCopy cregion = { .srcSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
- .dstSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
- .extent = {ctx->pSurf->width,ctx->pSurf->height,1}};
- vkCmdCopyImage(ctx->cmd,
- vkh_image_get_vkimage (savStencil), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- vkh_image_get_vkimage (ctx->pSurf->stencil),VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1, &cregion);
- vkh_image_set_layout (ctx->cmd, ctx->pSurf->stencil, ctx->dev->stencilAspectFlag,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
-
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_end (ctx->cmd);
+ vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, ctx->dev->stencilAspectFlag,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout(ctx->cmd, savStencil, ctx->dev->stencilAspectFlag,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ VkImageCopy cregion = {.srcSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
+ .dstSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
+ .extent = {ctx->pSurf->width, ctx->pSurf->height, 1}};
+ vkCmdCopyImage(ctx->cmd, vkh_image_get_vkimage(savStencil), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vkh_image_get_vkimage(ctx->pSurf->stencil), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
+ &cregion);
+ vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, ctx->dev->stencilAspectFlag,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_end(ctx->cmd);
#endif
- VK_CHECK_RESULT(vkEndCommandBuffer(ctx->cmd));
- _wait_and_submit_cmd (ctx);
- if (!_wait_ctx_flush_end (ctx))
- return;
- vkh_image_destroy (savStencil);
- }
- }
-
- ctx->curClipState = vkvg_clip_state_none;
-
- ctx->dashOffset = sav->dashOffset;
- if (ctx->dashCount > 0)
- free (ctx->dashes);
- ctx->dashCount = sav->dashCount;
- if (ctx->dashCount > 0) {
- ctx->dashes = (float*)malloc (sizeof(float) * ctx->dashCount);
- memcpy (ctx->dashes, sav->dashes, sizeof(float) * ctx->dashCount);
- }
-
- ctx->lineWidth = sav->lineWidth;
- ctx->miterLimit = sav->miterLimit;
- ctx->curOperator= sav->curOperator;
- ctx->lineCap = sav->lineCap;
- ctx->lineJoin = sav->lineJoint;
- ctx->curFillRule= sav->curFillRule;
-
- ctx->selectedCharSize = sav->selectedCharSize;
- strcpy (ctx->selectedFontName, sav->selectedFontName);
-
- ctx->currentFont = sav->currentFont;
- ctx->textDirection= sav->textDirection;
-
- if (sav->pattern) {
- if (sav->pattern != ctx->pattern)
- _update_cur_pattern (ctx, sav->pattern);
- else
- vkvg_pattern_destroy(sav->pattern);
- } else {
- ctx->curColor = sav->curColor;
- _update_cur_pattern (ctx, NULL);
- }
-
- _free_ctx_save(sav);
-}
-
-void vkvg_translate (VkvgContext ctx, float dx, float dy){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_TRANSLATE, dx, dy);
- LOG(VKVG_LOG_INFO_CMD, "CMD: translate: %f, %f\n", dx, dy);
- _emit_draw_cmd_undrawn_vertices(ctx);
- vkvg_matrix_translate (&ctx->pushConsts.mat, dx, dy);
- _set_mat_inv_and_vkCmdPush (ctx);
-}
-void vkvg_scale (VkvgContext ctx, float sx, float sy){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SCALE, sx, sy);
- LOG(VKVG_LOG_INFO_CMD, "CMD: scale: %f, %f\n", sx, sy);
- _emit_draw_cmd_undrawn_vertices(ctx);
- vkvg_matrix_scale (&ctx->pushConsts.mat, sx, sy);
- _set_mat_inv_and_vkCmdPush (ctx);
-}
-void vkvg_rotate (VkvgContext ctx, float radians){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_ROTATE, radians);
- LOG(VKVG_LOG_INFO_CMD, "CMD: rotate: %f\n", radians);
- _emit_draw_cmd_undrawn_vertices(ctx);
- vkvg_matrix_rotate (&ctx->pushConsts.mat, radians);
- _set_mat_inv_and_vkCmdPush (ctx);
-}
-void vkvg_transform (VkvgContext ctx, const vkvg_matrix_t* matrix) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_TRANSFORM, matrix);
- LOG(VKVG_LOG_INFO_CMD, "CMD: transform: %f, %f, %f, %f, %f, %f\n", matrix->xx, matrix->yx, matrix->xy, matrix->yy, matrix->x0, matrix->y0);
- _emit_draw_cmd_undrawn_vertices(ctx);
- vkvg_matrix_t res;
- vkvg_matrix_multiply (&res, &ctx->pushConsts.mat, matrix);
- ctx->pushConsts.mat = res;
- _set_mat_inv_and_vkCmdPush (ctx);
-}
-void vkvg_identity_matrix (VkvgContext ctx) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_IDENTITY_MATRIX);
- LOG(VKVG_LOG_INFO_CMD, "CMD: identity_matrix:\n");
- _emit_draw_cmd_undrawn_vertices(ctx);
- vkvg_matrix_t im = VKVG_IDENTITY_MATRIX;
- ctx->pushConsts.mat = im;
- _set_mat_inv_and_vkCmdPush (ctx);
-}
-void vkvg_set_matrix (VkvgContext ctx, const vkvg_matrix_t* matrix){
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_SET_MATRIX, matrix);
- LOG(VKVG_LOG_INFO_CMD, "CMD: set_matrix: %f, %f, %f, %f, %f, %f\n", matrix->xx, matrix->yx, matrix->xy, matrix->yy, matrix->x0, matrix->y0);
- _emit_draw_cmd_undrawn_vertices(ctx);
- ctx->pushConsts.mat = (*matrix);
- _set_mat_inv_and_vkCmdPush (ctx);
-}
-void vkvg_get_matrix (VkvgContext ctx, vkvg_matrix_t* const matrix){
- *matrix = ctx->pushConsts.mat;
-}
-
-void vkvg_elliptic_arc_to (VkvgContext ctx, float x2, float y2, bool largeArc, bool sweepFlag, float rx, float ry, float phi) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_ELLIPTICAL_ARC_TO, x2, y2, rx, ry, phi, largeArc, sweepFlag);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: elliptic_arc_to: x2:%10.5f y2:%10.5f large:%d sweep:%d rx:%10.5f ry:%10.5f phi:%10.5f \n", x2,y2,largeArc,sweepFlag,rx,ry,phi);
- float x1, y1;
- vkvg_get_current_point(ctx, &x1, &y1);
- _elliptic_arc(ctx, x1, y1, x2, y2, largeArc, sweepFlag, rx, ry, phi);
-}
-void vkvg_rel_elliptic_arc_to (VkvgContext ctx, float x2, float y2, bool largeArc, bool sweepFlag, float rx, float ry, float phi) {
- if (ctx->status)
- return;
- RECORD(ctx, VKVG_CMD_REL_ELLIPTICAL_ARC_TO, x2, y2, rx, ry, phi, largeArc, sweepFlag);
- LOG(VKVG_LOG_INFO_CMD, "\tCMD: rel_elliptic_arc_to: x2:%10.5f y2:%10.5f large:%d sweep:%d rx:%10.5f ry:%10.5f phi:%10.5f \n", x2,y2,largeArc,sweepFlag,rx,ry,phi);
-
- float x1, y1;
- vkvg_get_current_point(ctx, &x1, &y1);
- _elliptic_arc(ctx, x1, y1, x2+x1, y2+y1, largeArc, sweepFlag, rx, ry, phi);
-}
-
-void vkvg_ellipse (VkvgContext ctx, float radiusX, float radiusY, float x, float y, float rotationAngle) {
- if (ctx->status)
- return;
- LOG(VKVG_LOG_INFO_CMD, "CMD: ellipse:\n");
-
- float width_two_thirds = radiusX * 4 / 3;
-
- float dx1 = sinf(rotationAngle) * radiusY;
- float dy1 = cosf(rotationAngle) * radiusY;
- float dx2 = cosf(rotationAngle) * width_two_thirds;
- float dy2 = sinf(rotationAngle) * width_two_thirds;
-
- float topCenterX = x - dx1;
- float topCenterY = y + dy1;
- float topRightX = topCenterX + dx2;
- float topRightY = topCenterY + dy2;
- float topLeftX = topCenterX - dx2;
- float topLeftY = topCenterY - dy2;
-
- float bottomCenterX = x + dx1;
- float bottomCenterY = y - dy1;
- float bottomRightX = bottomCenterX + dx2;
- float bottomRightY = bottomCenterY + dy2;
- float bottomLeftX = bottomCenterX - dx2;
- float bottomLeftY = bottomCenterY - dy2;
-
- _finish_path(ctx);
- _add_point (ctx, bottomCenterX, bottomCenterY);
-
- _curve_to (ctx, bottomRightX, bottomRightY, topRightX, topRightY, topCenterX, topCenterY);
- _curve_to (ctx, topLeftX, topLeftY, bottomLeftX, bottomLeftY, bottomCenterX, bottomCenterY);
-
- ctx->pathes[ctx->pathPtr] |= PATH_CLOSED_BIT;
- _finish_path(ctx);
-}
-
-VkvgSurface vkvg_get_target (VkvgContext ctx) {
- if (ctx->status)
- return NULL;
- return ctx->pSurf;
-}
-
-const char *
-vkvg_status_to_string (vkvg_status_t status) {
- switch (status) {
- case VKVG_STATUS_SUCCESS:
- return "no error has occurred";
- case VKVG_STATUS_NO_MEMORY:
- return "out of memory";
- case VKVG_STATUS_INVALID_RESTORE:
- return "vkvg_restore() without matching vkvg_save()";
- case VKVG_STATUS_NO_CURRENT_POINT:
- return "no current point defined";
- case VKVG_STATUS_INVALID_MATRIX:
- return "invalid matrix (not invertible)";
- case VKVG_STATUS_INVALID_STATUS:
- return "invalid value for an input vkvg_status_t";
- case VKVG_STATUS_INVALID_INDEX:
- return "invalid index passed to getter";
- case VKVG_STATUS_NULL_POINTER:
- return "NULL pointer";
- case VKVG_STATUS_WRITE_ERROR:
- return "error while writing to output stream";
- case VKVG_STATUS_PATTERN_TYPE_MISMATCH:
- return "the pattern type is not appropriate for the operation";
- case VKVG_STATUS_PATTERN_INVALID_GRADIENT:
- return "the stops count is zero";
- case VKVG_STATUS_INVALID_FORMAT:
- return "invalid value for an input vkvg_format_t";
- case VKVG_STATUS_FILE_NOT_FOUND:
- return "file not found";
- case VKVG_STATUS_INVALID_DASH:
- return "invalid value for a dash setting";
- case VKVG_STATUS_INVALID_RECT:
- return "a rectangle has the height or width equal to 0";
- case VKVG_STATUS_TIMEOUT:
- return "waiting for a Vulkan operation to finish resulted in a fence timeout (5 seconds)";
- case VKVG_STATUS_DEVICE_ERROR:
- return "the initialization of the device resulted in an error";
- case VKVG_STATUS_INVALID_IMAGE:
- return "invalid image";
- case VKVG_STATUS_INVALID_SURFACE:
- return "invalid surface";
- case VKVG_STATUS_INVALID_FONT:
- return "unresolved font name";
- default:
- return "<unknown error status>";
- }
+ VK_CHECK_RESULT(vkEndCommandBuffer(ctx->cmd));
+ _wait_and_submit_cmd(ctx);
+ if (!_wait_ctx_flush_end(ctx))
+ return;
+ vkh_image_destroy(savStencil);
+ }
+ }
+
+ ctx->curClipState = vkvg_clip_state_none;
+
+ ctx->dashOffset = sav->dashOffset;
+ if (ctx->dashCount > 0)
+ free(ctx->dashes);
+ ctx->dashCount = sav->dashCount;
+ if (ctx->dashCount > 0) {
+ ctx->dashes = (float *)malloc(sizeof(float) * ctx->dashCount);
+ memcpy(ctx->dashes, sav->dashes, sizeof(float) * ctx->dashCount);
+ }
+
+ ctx->lineWidth = sav->lineWidth;
+ ctx->miterLimit = sav->miterLimit;
+ ctx->curOperator = sav->curOperator;
+ ctx->lineCap = sav->lineCap;
+ ctx->lineJoin = sav->lineJoint;
+ ctx->curFillRule = sav->curFillRule;
+
+ ctx->selectedCharSize = sav->selectedCharSize;
+ strcpy(ctx->selectedFontName, sav->selectedFontName);
+
+ ctx->currentFont = sav->currentFont;
+ ctx->textDirection = sav->textDirection;
+
+ if (sav->pattern) {
+ if (sav->pattern != ctx->pattern)
+ _update_cur_pattern(ctx, sav->pattern);
+ else
+ vkvg_pattern_destroy(sav->pattern);
+ } else {
+ ctx->curColor = sav->curColor;
+ _update_cur_pattern(ctx, NULL);
+ }
+
+ _free_ctx_save(sav);
+}
+
+void vkvg_translate(VkvgContext ctx, float dx, float dy) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_TRANSLATE, dx, dy);
+ LOG(VKVG_LOG_INFO_CMD, "CMD: translate: %f, %f\n", dx, dy);
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ vkvg_matrix_translate(&ctx->pushConsts.mat, dx, dy);
+ _set_mat_inv_and_vkCmdPush(ctx);
+}
+void vkvg_scale(VkvgContext ctx, float sx, float sy) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SCALE, sx, sy);
+ LOG(VKVG_LOG_INFO_CMD, "CMD: scale: %f, %f\n", sx, sy);
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ vkvg_matrix_scale(&ctx->pushConsts.mat, sx, sy);
+ _set_mat_inv_and_vkCmdPush(ctx);
+}
+void vkvg_rotate(VkvgContext ctx, float radians) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_ROTATE, radians);
+ LOG(VKVG_LOG_INFO_CMD, "CMD: rotate: %f\n", radians);
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ vkvg_matrix_rotate(&ctx->pushConsts.mat, radians);
+ _set_mat_inv_and_vkCmdPush(ctx);
+}
+void vkvg_transform(VkvgContext ctx, const vkvg_matrix_t *matrix) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_TRANSFORM, matrix);
+ LOG(VKVG_LOG_INFO_CMD, "CMD: transform: %f, %f, %f, %f, %f, %f\n", matrix->xx, matrix->yx, matrix->xy, matrix->yy,
+ matrix->x0, matrix->y0);
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ vkvg_matrix_t res;
+ vkvg_matrix_multiply(&res, &ctx->pushConsts.mat, matrix);
+ ctx->pushConsts.mat = res;
+ _set_mat_inv_and_vkCmdPush(ctx);
+}
+void vkvg_identity_matrix(VkvgContext ctx) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_IDENTITY_MATRIX);
+ LOG(VKVG_LOG_INFO_CMD, "CMD: identity_matrix:\n");
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ vkvg_matrix_t im = VKVG_IDENTITY_MATRIX;
+ ctx->pushConsts.mat = im;
+ _set_mat_inv_and_vkCmdPush(ctx);
+}
+void vkvg_set_matrix(VkvgContext ctx, const vkvg_matrix_t *matrix) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_SET_MATRIX, matrix);
+ LOG(VKVG_LOG_INFO_CMD, "CMD: set_matrix: %f, %f, %f, %f, %f, %f\n", matrix->xx, matrix->yx, matrix->xy, matrix->yy,
+ matrix->x0, matrix->y0);
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ ctx->pushConsts.mat = (*matrix);
+ _set_mat_inv_and_vkCmdPush(ctx);
+}
+void vkvg_get_matrix(VkvgContext ctx, vkvg_matrix_t *const matrix) { *matrix = ctx->pushConsts.mat; }
+
+void vkvg_elliptic_arc_to(VkvgContext ctx, float x2, float y2, bool largeArc, bool sweepFlag, float rx, float ry,
+ float phi) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_ELLIPTICAL_ARC_TO, x2, y2, rx, ry, phi, largeArc, sweepFlag);
+ LOG(VKVG_LOG_INFO_CMD,
+ "\tCMD: elliptic_arc_to: x2:%10.5f y2:%10.5f large:%d sweep:%d rx:%10.5f ry:%10.5f phi:%10.5f \n", x2, y2,
+ largeArc, sweepFlag, rx, ry, phi);
+ float x1, y1;
+ vkvg_get_current_point(ctx, &x1, &y1);
+ _elliptic_arc(ctx, x1, y1, x2, y2, largeArc, sweepFlag, rx, ry, phi);
+}
+void vkvg_rel_elliptic_arc_to(VkvgContext ctx, float x2, float y2, bool largeArc, bool sweepFlag, float rx, float ry,
+ float phi) {
+ if (ctx->status)
+ return;
+ RECORD(ctx, VKVG_CMD_REL_ELLIPTICAL_ARC_TO, x2, y2, rx, ry, phi, largeArc, sweepFlag);
+ LOG(VKVG_LOG_INFO_CMD,
+ "\tCMD: rel_elliptic_arc_to: x2:%10.5f y2:%10.5f large:%d sweep:%d rx:%10.5f ry:%10.5f phi:%10.5f \n", x2, y2,
+ largeArc, sweepFlag, rx, ry, phi);
+
+ float x1, y1;
+ vkvg_get_current_point(ctx, &x1, &y1);
+ _elliptic_arc(ctx, x1, y1, x2 + x1, y2 + y1, largeArc, sweepFlag, rx, ry, phi);
+}
+
+void vkvg_ellipse(VkvgContext ctx, float radiusX, float radiusY, float x, float y, float rotationAngle) {
+ if (ctx->status)
+ return;
+ LOG(VKVG_LOG_INFO_CMD, "CMD: ellipse:\n");
+
+ float width_two_thirds = radiusX * 4 / 3;
+
+ float dx1 = sinf(rotationAngle) * radiusY;
+ float dy1 = cosf(rotationAngle) * radiusY;
+ float dx2 = cosf(rotationAngle) * width_two_thirds;
+ float dy2 = sinf(rotationAngle) * width_two_thirds;
+
+ float topCenterX = x - dx1;
+ float topCenterY = y + dy1;
+ float topRightX = topCenterX + dx2;
+ float topRightY = topCenterY + dy2;
+ float topLeftX = topCenterX - dx2;
+ float topLeftY = topCenterY - dy2;
+
+ float bottomCenterX = x + dx1;
+ float bottomCenterY = y - dy1;
+ float bottomRightX = bottomCenterX + dx2;
+ float bottomRightY = bottomCenterY + dy2;
+ float bottomLeftX = bottomCenterX - dx2;
+ float bottomLeftY = bottomCenterY - dy2;
+
+ _finish_path(ctx);
+ _add_point(ctx, bottomCenterX, bottomCenterY);
+
+ _curve_to(ctx, bottomRightX, bottomRightY, topRightX, topRightY, topCenterX, topCenterY);
+ _curve_to(ctx, topLeftX, topLeftY, bottomLeftX, bottomLeftY, bottomCenterX, bottomCenterY);
+
+ ctx->pathes[ctx->pathPtr] |= PATH_CLOSED_BIT;
+ _finish_path(ctx);
+}
+
+VkvgSurface vkvg_get_target(VkvgContext ctx) {
+ if (ctx->status)
+ return NULL;
+ return ctx->pSurf;
+}
+
+const char *vkvg_status_to_string(vkvg_status_t status) {
+ switch (status) {
+ case VKVG_STATUS_SUCCESS:
+ return "no error has occurred";
+ case VKVG_STATUS_NO_MEMORY:
+ return "out of memory";
+ case VKVG_STATUS_INVALID_RESTORE:
+ return "vkvg_restore() without matching vkvg_save()";
+ case VKVG_STATUS_NO_CURRENT_POINT:
+ return "no current point defined";
+ case VKVG_STATUS_INVALID_MATRIX:
+ return "invalid matrix (not invertible)";
+ case VKVG_STATUS_INVALID_STATUS:
+ return "invalid value for an input vkvg_status_t";
+ case VKVG_STATUS_INVALID_INDEX:
+ return "invalid index passed to getter";
+ case VKVG_STATUS_NULL_POINTER:
+ return "NULL pointer";
+ case VKVG_STATUS_WRITE_ERROR:
+ return "error while writing to output stream";
+ case VKVG_STATUS_PATTERN_TYPE_MISMATCH:
+ return "the pattern type is not appropriate for the operation";
+ case VKVG_STATUS_PATTERN_INVALID_GRADIENT:
+ return "the stops count is zero";
+ case VKVG_STATUS_INVALID_FORMAT:
+ return "invalid value for an input vkvg_format_t";
+ case VKVG_STATUS_FILE_NOT_FOUND:
+ return "file not found";
+ case VKVG_STATUS_INVALID_DASH:
+ return "invalid value for a dash setting";
+ case VKVG_STATUS_INVALID_RECT:
+ return "a rectangle has the height or width equal to 0";
+ case VKVG_STATUS_TIMEOUT:
+ return "waiting for a Vulkan operation to finish resulted in a fence timeout (5 seconds)";
+ case VKVG_STATUS_DEVICE_ERROR:
+ return "the initialization of the device resulted in an error";
+ case VKVG_STATUS_INVALID_IMAGE:
+ return "invalid image";
+ case VKVG_STATUS_INVALID_SURFACE:
+ return "invalid surface";
+ case VKVG_STATUS_INVALID_FONT:
+ return "unresolved font name";
+ default:
+ return "<unknown error status>";
+ }
}
* THE SOFTWARE.
*/
-//credits for bezier algorithms to:
+// credits for bezier algorithms to:
// Anti-Grain Geometry (AGG) - Version 2.5
// A high quality rendering engine for C++
// Copyright (C) 2002-2006 Maxim Shemanarev
// mcseemagg@yahoo.com
// http://antigrain.com
-
#include "vkvg_surface_internal.h"
#include "vkvg_context_internal.h"
#include "vkvg_device_internal.h"
#include "glutess.h"
#endif
-void _resize_vertex_cache (VkvgContext ctx, uint32_t newSize) {
- Vertex* tmp = (Vertex*) realloc (ctx->vertexCache, (size_t)newSize * sizeof(Vertex));
- LOG(VKVG_LOG_DBG_ARRAYS, "resize vertex cache (vx count=%u): old size: %u -> new size: %u size(byte): %zu Ptr: %p -> %p\n",
- ctx->vertCount, ctx->sizeVertices, newSize, (size_t)newSize * sizeof(Vertex), ctx->vertexCache, tmp);
- if (tmp == NULL){
- ctx->status = VKVG_STATUS_NO_MEMORY;
- LOG(VKVG_LOG_ERR, "resize vertex cache failed: vert count: %u byte size: %zu\n", newSize, newSize * sizeof(Vertex));
- return;
- }
- ctx->vertexCache = tmp;
- ctx->sizeVertices = newSize;
-}
-void _resize_index_cache (VkvgContext ctx, uint32_t newSize) {
- VKVG_IBO_INDEX_TYPE* tmp = (VKVG_IBO_INDEX_TYPE*) realloc (ctx->indexCache, (size_t)newSize * sizeof(VKVG_IBO_INDEX_TYPE));
- LOG(VKVG_LOG_DBG_ARRAYS, "resize IBO: new size: %lu Ptr: %p -> %p\n", (size_t)newSize * sizeof(VKVG_IBO_INDEX_TYPE), ctx->indexCache, tmp);
- if (tmp == NULL){
- ctx->status = VKVG_STATUS_NO_MEMORY;
- LOG(VKVG_LOG_ERR, "resize IBO failed: idx count: %u size(byte): %zu\n", newSize, (size_t)newSize * sizeof(VKVG_IBO_INDEX_TYPE));
- return;
- }
- ctx->indexCache = tmp;
- ctx->sizeIndices = newSize;
-}
-void _ensure_vertex_cache_size (VkvgContext ctx, uint32_t addedVerticesCount) {
- if (ctx->sizeVertices - ctx->vertCount > VKVG_ARRAY_THRESHOLD + addedVerticesCount)
- return;
- uint32_t newSize = ctx->sizeVertices + addedVerticesCount;
- uint32_t modulo = addedVerticesCount % VKVG_VBO_SIZE;
- if (modulo > 0)
- newSize += VKVG_VBO_SIZE - modulo;
- _resize_vertex_cache (ctx, newSize);
-}
-void _check_vertex_cache_size (VkvgContext ctx) {
- assert(ctx->sizeVertices > ctx->vertCount);
- if (ctx->sizeVertices - VKVG_ARRAY_THRESHOLD > ctx->vertCount)
- return;
- _resize_vertex_cache (ctx, ctx->sizeVertices + VKVG_VBO_SIZE);
-}
-void _ensure_index_cache_size (VkvgContext ctx, uint32_t addedIndicesCount) {
- assert(ctx->sizeIndices > ctx->indCount);
- if (ctx->sizeIndices - VKVG_ARRAY_THRESHOLD > ctx->indCount + addedIndicesCount)
- return;
- uint32_t newSize = ctx->sizeIndices + addedIndicesCount;
- uint32_t modulo = addedIndicesCount % VKVG_IBO_SIZE;
- if (modulo > 0)
- newSize += VKVG_IBO_SIZE - modulo;
- _resize_index_cache (ctx, newSize);
-}
-void _check_index_cache_size (VkvgContext ctx) {
- if (ctx->sizeIndices - VKVG_ARRAY_THRESHOLD > ctx->indCount)
- return;
- _resize_index_cache (ctx, ctx->sizeIndices + VKVG_IBO_SIZE);
-}
-//check host path array size, return true if error. pathPtr is already incremented
-bool _check_pathes_array (VkvgContext ctx){
- if (ctx->sizePathes - ctx->pathPtr - ctx->segmentPtr > VKVG_ARRAY_THRESHOLD)
- return false;
- ctx->sizePathes += VKVG_PATHES_SIZE;
- uint32_t* tmp = (uint32_t*) realloc (ctx->pathes, (size_t)ctx->sizePathes * sizeof(uint32_t));
- LOG(VKVG_LOG_DBG_ARRAYS, "resize PATH: new size: %u Ptr: %p -> %p\n", ctx->sizePathes, ctx->pathes, tmp);
- if (tmp == NULL){
- ctx->status = VKVG_STATUS_NO_MEMORY;
- LOG(VKVG_LOG_ERR, "resize PATH failed: new size(byte): %zu\n", ctx->sizePathes * sizeof(uint32_t));
- _clear_path(ctx);
- return true;
- }
- ctx->pathes = tmp;
- return false;
-}
-//check host point array size, return true if error
-bool _check_point_array (VkvgContext ctx){
- if (ctx->sizePoints - VKVG_ARRAY_THRESHOLD > ctx->pointCount)
- return false;
- ctx->sizePoints += VKVG_PTS_SIZE;
- vec2* tmp = (vec2*) realloc (ctx->points, (size_t)ctx->sizePoints * sizeof(vec2));
- LOG(VKVG_LOG_DBG_ARRAYS, "resize Points: new size(point): %u Ptr: %p -> %p\n", ctx->sizePoints, ctx->points, tmp);
- if (tmp == NULL){
- ctx->status = VKVG_STATUS_NO_MEMORY;
- LOG(VKVG_LOG_ERR, "resize PATH failed: new size(byte): %zu\n", ctx->sizePoints * sizeof(vec2));
- _clear_path (ctx);
- return true;
- }
- ctx->points = tmp;
- return false;
-}
-bool _current_path_is_empty (VkvgContext ctx) {
- return ctx->pathes [ctx->pathPtr] == 0;
-}
-//this function expect that current point exists
-vec2 _get_current_position (VkvgContext ctx) {
- return ctx->points[ctx->pointCount-1];
-}
-//set curve start point and set path has curve bit
-void _set_curve_start (VkvgContext ctx) {
- if (ctx->segmentPtr > 0) {
- //check if current segment has points (straight)
- if ((ctx->pathes [ctx->pathPtr + ctx->segmentPtr]&PATH_ELT_MASK) > 0)
- ctx->segmentPtr++;
- }else{
- //not yet segmented path, first segment length is copied
- if (ctx->pathes [ctx->pathPtr] > 0){//create first straight segment first
- ctx->pathes [ctx->pathPtr + 1] = ctx->pathes [ctx->pathPtr];
- ctx->segmentPtr = 2;
- }else
- ctx->segmentPtr = 1;
- }
- _check_pathes_array(ctx);
- ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = 0;
-}
-//compute segment length and set is curved bit
-void _set_curve_end (VkvgContext ctx) {
- //ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = ctx->pathes [ctx->pathPtr] - ctx->pathes [ctx->pathPtr + ctx->segmentPtr];
- ctx->pathes [ctx->pathPtr + ctx->segmentPtr] |= PATH_HAS_CURVES_BIT;
- ctx->segmentPtr++;
- _check_pathes_array(ctx);
- ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = 0;
-}
-//path start pointed at ptrPath has curve bit
-bool _path_has_curves (VkvgContext ctx, uint32_t ptrPath) {
- return ctx->pathes[ptrPath] & PATH_HAS_CURVES_BIT;
-}
-void _finish_path (VkvgContext ctx){
- if (ctx->pathes [ctx->pathPtr] == 0)//empty
- return;
- if ((ctx->pathes [ctx->pathPtr]&PATH_ELT_MASK) < 2){
- //only current pos is in path
- ctx->pointCount -= ctx->pathes[ctx->pathPtr];//what about the bounds?
- ctx->pathes[ctx->pathPtr] = 0;
- ctx->segmentPtr = 0;
- return;
- }
-
- LOG(VKVG_LOG_INFO_PATH, "PATH: points count=%10d\n", ctx->pathes[ctx->pathPtr]&PATH_ELT_MASK);
-
- if (ctx->pathPtr == 0 && ctx->simpleConvex)
- ctx->pathes[0] |= PATH_IS_CONVEX_BIT;
-
- if (ctx->segmentPtr > 0) {//pathes having curves are segmented
- ctx->pathes[ctx->pathPtr] |= PATH_HAS_CURVES_BIT;
- //curved segment increment segmentPtr on curve end,
- //so if last segment is not a curve and point count > 0
- if ((ctx->pathes[ctx->pathPtr+ctx->segmentPtr]&PATH_HAS_CURVES_BIT)==0 &&
- (ctx->pathes[ctx->pathPtr+ctx->segmentPtr]&PATH_ELT_MASK) > 0)
- ctx->segmentPtr++;//current segment has to be included
- ctx->pathPtr += ctx->segmentPtr;
- }else
- ctx->pathPtr ++;
-
- if (_check_pathes_array(ctx))
- return;
-
- ctx->pathes[ctx->pathPtr] = 0;
- ctx->segmentPtr = 0;
- ctx->subpathCount++;
- ctx->simpleConvex = false;
-}
-//clear path datas in context
-void _clear_path (VkvgContext ctx){
- ctx->pathPtr = 0;
- ctx->pathes [ctx->pathPtr] = 0;
- ctx->pointCount = 0;
- ctx->segmentPtr = 0;
- ctx->subpathCount = 0;
- ctx->simpleConvex = false;
-}
-void _remove_last_point (VkvgContext ctx){
- ctx->pathes[ctx->pathPtr]--;
- ctx->pointCount--;
- if (ctx->segmentPtr > 0){//if path is segmented
- if (!ctx->pathes [ctx->pathPtr + ctx->segmentPtr])//if current segment is empty
- ctx->segmentPtr--;
- ctx->pathes [ctx->pathPtr + ctx->segmentPtr]--;//decrement last segment point count
- if ((ctx->pathes [ctx->pathPtr + ctx->segmentPtr]&PATH_ELT_MASK) == 0)//if no point left (was only one)
- ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = 0;//reset current segment
- else if (ctx->pathes [ctx->pathPtr + ctx->segmentPtr]&PATH_HAS_CURVES_BIT)//if segment is a curve
- ctx->segmentPtr++;//then segPtr has to be forwarded to new segment
- }
-}
-bool _path_is_closed (VkvgContext ctx, uint32_t ptrPath){
- return ctx->pathes[ptrPath] & PATH_CLOSED_BIT;
-}
-void _add_point (VkvgContext ctx, float x, float y){
- if (_check_point_array(ctx))
- return;
- if (isnan(x) || isnan(y)) {
- LOG(VKVG_LOG_DEBUG, "_add_point: (%f, %f)\n", x, y);
- return;
- }
- vec2 v = {x,y};
- /*if (!_current_path_is_empty(ctx) && vec2_length(vec2_sub(ctx->points[ctx->pointCount-1], v))<1.f)
- return;*/
- LOG(VKVG_LOG_INFO_PTS, "_add_point: (%f, %f)\n", x, y);
-
- ctx->points[ctx->pointCount] = v;
- ctx->pointCount++;//total point count of pathes, (for array bounds check)
- ctx->pathes[ctx->pathPtr]++;//total point count in path
- if (ctx->segmentPtr > 0)
- ctx->pathes[ctx->pathPtr + ctx->segmentPtr]++;//total point count in path's segment
-}
-float _normalizeAngle(float a)
-{
- float res = ROUND_DOWN(fmodf(a, 2.0f * M_PIF), 100);
- if (res < 0.0f)
- res += 2.0f * M_PIF;
- return res;
-}
-float _get_arc_step (VkvgContext ctx, float radius) {
- float sx, sy;
- vkvg_matrix_get_scale (&ctx->pushConsts.mat, &sx, &sy);
- float r = radius * fabsf(fmaxf(sx,sy));
- if (r < 30.0f)
- return fminf(M_PIF / 3.f, M_PIF / r);
- return fminf(M_PIF / 3.f,M_PIF / (r * 0.4f));
-}
-void _create_gradient_buff (VkvgContext ctx){
- vkh_buffer_init ((VkhDevice)ctx->dev,
- VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
- VKH_MEMORY_USAGE_CPU_TO_GPU,
- sizeof(vkvg_gradient_t), &ctx->uboGrad, true);
-}
-void _create_vertices_buff (VkvgContext ctx){
- vkh_buffer_init ((VkhDevice)ctx->dev,
- VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
- VKH_MEMORY_USAGE_CPU_TO_GPU,
- ctx->sizeVBO * sizeof(Vertex), &ctx->vertices, true);
- vkh_buffer_init ((VkhDevice)ctx->dev,
- VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
- VKH_MEMORY_USAGE_CPU_TO_GPU,
- ctx->sizeIBO * sizeof(VKVG_IBO_INDEX_TYPE), &ctx->indices, true);
-}
-void _resize_vbo (VkvgContext ctx, uint32_t new_size) {
- if (!_wait_ctx_flush_end (ctx))//wait previous cmd if not completed
- return;
- LOG(VKVG_LOG_DBG_ARRAYS, "resize VBO: %d -> ", ctx->sizeVBO);
- ctx->sizeVBO = new_size;
- uint32_t mod = ctx->sizeVBO % VKVG_VBO_SIZE;
- if (mod > 0)
- ctx->sizeVBO += VKVG_VBO_SIZE - mod;
- LOG(VKVG_LOG_DBG_ARRAYS, "%d\n", ctx->sizeVBO);
- vkh_buffer_resize (&ctx->vertices, ctx->sizeVBO * sizeof(Vertex), true);
-}
-void _resize_ibo (VkvgContext ctx, size_t new_size) {
- if (!_wait_ctx_flush_end (ctx))//wait previous cmd if not completed
- return;
- ctx->sizeIBO = new_size;
- uint32_t mod = ctx->sizeIBO % VKVG_IBO_SIZE;
- if (mod > 0)
- ctx->sizeIBO += VKVG_IBO_SIZE - mod;
- LOG(VKVG_LOG_DBG_ARRAYS, "resize IBO: new size: %d\n", ctx->sizeIBO);
- vkh_buffer_resize (&ctx->indices, ctx->sizeIBO * sizeof(VKVG_IBO_INDEX_TYPE), true);
-}
-void _add_vertexf (VkvgContext ctx, float x, float y){
- Vertex* pVert = &ctx->vertexCache[ctx->vertCount];
- pVert->pos.x = x;
- pVert->pos.y = y;
- pVert->color = ctx->curColor;
- pVert->uv.z = -1;
- LOG(VKVG_LOG_INFO_VBO, "Add Vertexf %10d: pos:(%10.4f, %10.4f) uv:(%10.4f,%10.4f,%10.4f) color:0x%.8x \n", ctx->vertCount, pVert->pos.x, pVert->pos.y, pVert->uv.x, pVert->uv.y, pVert->uv.z, pVert->color);
- ctx->vertCount++;
- _check_vertex_cache_size(ctx);
-}
-void _add_vertexf_unchecked (VkvgContext ctx, float x, float y){
- Vertex* pVert = &ctx->vertexCache[ctx->vertCount];
- pVert->pos.x = x;
- pVert->pos.y = y;
- pVert->color = ctx->curColor;
- pVert->uv.z = -1;
- LOG(VKVG_LOG_INFO_VBO, "Add Vertexf %10d: pos:(%10.4f, %10.4f) uv:(%10.4f,%10.4f,%10.4f) color:0x%.8x \n", ctx->vertCount, pVert->pos.x, pVert->pos.y, pVert->uv.x, pVert->uv.y, pVert->uv.z, pVert->color);
- ctx->vertCount++;
-}
-void _add_vertex(VkvgContext ctx, Vertex v){
- ctx->vertexCache[ctx->vertCount] = v;
- LOG(VKVG_LOG_INFO_VBO, "Add Vertex %10d: pos:(%10.4f, %10.4f) uv:(%10.4f,%10.4f,%10.4f) color:0x%.8x \n", ctx->vertCount, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.uv.z, v.color);
- ctx->vertCount++;
- _check_vertex_cache_size(ctx);
-}
-void _set_vertex(VkvgContext ctx, uint32_t idx, Vertex v){
- ctx->vertexCache[idx] = v;
-}
+void _resize_vertex_cache(VkvgContext ctx, uint32_t newSize) {
+ Vertex *tmp = (Vertex *)realloc(ctx->vertexCache, (size_t)newSize * sizeof(Vertex));
+ LOG(VKVG_LOG_DBG_ARRAYS,
+ "resize vertex cache (vx count=%u): old size: %u -> new size: %u size(byte): %zu Ptr: %p -> %p\n",
+ ctx->vertCount, ctx->sizeVertices, newSize, (size_t)newSize * sizeof(Vertex), ctx->vertexCache, tmp);
+ if (tmp == NULL) {
+ ctx->status = VKVG_STATUS_NO_MEMORY;
+ LOG(VKVG_LOG_ERR, "resize vertex cache failed: vert count: %u byte size: %zu\n", newSize,
+ newSize * sizeof(Vertex));
+ return;
+ }
+ ctx->vertexCache = tmp;
+ ctx->sizeVertices = newSize;
+}
+void _resize_index_cache(VkvgContext ctx, uint32_t newSize) {
+ VKVG_IBO_INDEX_TYPE *tmp =
+ (VKVG_IBO_INDEX_TYPE *)realloc(ctx->indexCache, (size_t)newSize * sizeof(VKVG_IBO_INDEX_TYPE));
+ LOG(VKVG_LOG_DBG_ARRAYS, "resize IBO: new size: %lu Ptr: %p -> %p\n", (size_t)newSize * sizeof(VKVG_IBO_INDEX_TYPE),
+ ctx->indexCache, tmp);
+ if (tmp == NULL) {
+ ctx->status = VKVG_STATUS_NO_MEMORY;
+ LOG(VKVG_LOG_ERR, "resize IBO failed: idx count: %u size(byte): %zu\n", newSize,
+ (size_t)newSize * sizeof(VKVG_IBO_INDEX_TYPE));
+ return;
+ }
+ ctx->indexCache = tmp;
+ ctx->sizeIndices = newSize;
+}
+void _ensure_vertex_cache_size(VkvgContext ctx, uint32_t addedVerticesCount) {
+ if (ctx->sizeVertices - ctx->vertCount > VKVG_ARRAY_THRESHOLD + addedVerticesCount)
+ return;
+ uint32_t newSize = ctx->sizeVertices + addedVerticesCount;
+ uint32_t modulo = addedVerticesCount % VKVG_VBO_SIZE;
+ if (modulo > 0)
+ newSize += VKVG_VBO_SIZE - modulo;
+ _resize_vertex_cache(ctx, newSize);
+}
+void _check_vertex_cache_size(VkvgContext ctx) {
+ assert(ctx->sizeVertices > ctx->vertCount);
+ if (ctx->sizeVertices - VKVG_ARRAY_THRESHOLD > ctx->vertCount)
+ return;
+ _resize_vertex_cache(ctx, ctx->sizeVertices + VKVG_VBO_SIZE);
+}
+void _ensure_index_cache_size(VkvgContext ctx, uint32_t addedIndicesCount) {
+ assert(ctx->sizeIndices > ctx->indCount);
+ if (ctx->sizeIndices - VKVG_ARRAY_THRESHOLD > ctx->indCount + addedIndicesCount)
+ return;
+ uint32_t newSize = ctx->sizeIndices + addedIndicesCount;
+ uint32_t modulo = addedIndicesCount % VKVG_IBO_SIZE;
+ if (modulo > 0)
+ newSize += VKVG_IBO_SIZE - modulo;
+ _resize_index_cache(ctx, newSize);
+}
+void _check_index_cache_size(VkvgContext ctx) {
+ if (ctx->sizeIndices - VKVG_ARRAY_THRESHOLD > ctx->indCount)
+ return;
+ _resize_index_cache(ctx, ctx->sizeIndices + VKVG_IBO_SIZE);
+}
+// check host path array size, return true if error. pathPtr is already incremented
+bool _check_pathes_array(VkvgContext ctx) {
+ if (ctx->sizePathes - ctx->pathPtr - ctx->segmentPtr > VKVG_ARRAY_THRESHOLD)
+ return false;
+ ctx->sizePathes += VKVG_PATHES_SIZE;
+ uint32_t *tmp = (uint32_t *)realloc(ctx->pathes, (size_t)ctx->sizePathes * sizeof(uint32_t));
+ LOG(VKVG_LOG_DBG_ARRAYS, "resize PATH: new size: %u Ptr: %p -> %p\n", ctx->sizePathes, ctx->pathes, tmp);
+ if (tmp == NULL) {
+ ctx->status = VKVG_STATUS_NO_MEMORY;
+ LOG(VKVG_LOG_ERR, "resize PATH failed: new size(byte): %zu\n", ctx->sizePathes * sizeof(uint32_t));
+ _clear_path(ctx);
+ return true;
+ }
+ ctx->pathes = tmp;
+ return false;
+}
+// check host point array size, return true if error
+bool _check_point_array(VkvgContext ctx) {
+ if (ctx->sizePoints - VKVG_ARRAY_THRESHOLD > ctx->pointCount)
+ return false;
+ ctx->sizePoints += VKVG_PTS_SIZE;
+ vec2 *tmp = (vec2 *)realloc(ctx->points, (size_t)ctx->sizePoints * sizeof(vec2));
+ LOG(VKVG_LOG_DBG_ARRAYS, "resize Points: new size(point): %u Ptr: %p -> %p\n", ctx->sizePoints, ctx->points, tmp);
+ if (tmp == NULL) {
+ ctx->status = VKVG_STATUS_NO_MEMORY;
+ LOG(VKVG_LOG_ERR, "resize PATH failed: new size(byte): %zu\n", ctx->sizePoints * sizeof(vec2));
+ _clear_path(ctx);
+ return true;
+ }
+ ctx->points = tmp;
+ return false;
+}
+bool _current_path_is_empty(VkvgContext ctx) { return ctx->pathes[ctx->pathPtr] == 0; }
+// this function expect that current point exists
+vec2 _get_current_position(VkvgContext ctx) { return ctx->points[ctx->pointCount - 1]; }
+// set curve start point and set path has curve bit
+void _set_curve_start(VkvgContext ctx) {
+ if (ctx->segmentPtr > 0) {
+ // check if current segment has points (straight)
+ if ((ctx->pathes[ctx->pathPtr + ctx->segmentPtr] & PATH_ELT_MASK) > 0)
+ ctx->segmentPtr++;
+ } else {
+ // not yet segmented path, first segment length is copied
+ if (ctx->pathes[ctx->pathPtr] > 0) { // create first straight segment first
+ ctx->pathes[ctx->pathPtr + 1] = ctx->pathes[ctx->pathPtr];
+ ctx->segmentPtr = 2;
+ } else
+ ctx->segmentPtr = 1;
+ }
+ _check_pathes_array(ctx);
+ ctx->pathes[ctx->pathPtr + ctx->segmentPtr] = 0;
+}
+// compute segment length and set is curved bit
+void _set_curve_end(VkvgContext ctx) {
+ // ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = ctx->pathes [ctx->pathPtr] - ctx->pathes [ctx->pathPtr +
+ // ctx->segmentPtr];
+ ctx->pathes[ctx->pathPtr + ctx->segmentPtr] |= PATH_HAS_CURVES_BIT;
+ ctx->segmentPtr++;
+ _check_pathes_array(ctx);
+ ctx->pathes[ctx->pathPtr + ctx->segmentPtr] = 0;
+}
+// path start pointed at ptrPath has curve bit
+bool _path_has_curves(VkvgContext ctx, uint32_t ptrPath) { return ctx->pathes[ptrPath] & PATH_HAS_CURVES_BIT; }
+void _finish_path(VkvgContext ctx) {
+ if (ctx->pathes[ctx->pathPtr] == 0) // empty
+ return;
+ if ((ctx->pathes[ctx->pathPtr] & PATH_ELT_MASK) < 2) {
+ // only current pos is in path
+ ctx->pointCount -= ctx->pathes[ctx->pathPtr]; // what about the bounds?
+ ctx->pathes[ctx->pathPtr] = 0;
+ ctx->segmentPtr = 0;
+ return;
+ }
+
+ LOG(VKVG_LOG_INFO_PATH, "PATH: points count=%10d\n", ctx->pathes[ctx->pathPtr] & PATH_ELT_MASK);
+
+ if (ctx->pathPtr == 0 && ctx->simpleConvex)
+ ctx->pathes[0] |= PATH_IS_CONVEX_BIT;
+
+ if (ctx->segmentPtr > 0) { // pathes having curves are segmented
+ ctx->pathes[ctx->pathPtr] |= PATH_HAS_CURVES_BIT;
+ // curved segment increment segmentPtr on curve end,
+ // so if last segment is not a curve and point count > 0
+ if ((ctx->pathes[ctx->pathPtr + ctx->segmentPtr] & PATH_HAS_CURVES_BIT) == 0 &&
+ (ctx->pathes[ctx->pathPtr + ctx->segmentPtr] & PATH_ELT_MASK) > 0)
+ ctx->segmentPtr++; // current segment has to be included
+ ctx->pathPtr += ctx->segmentPtr;
+ } else
+ ctx->pathPtr++;
+
+ if (_check_pathes_array(ctx))
+ return;
+
+ ctx->pathes[ctx->pathPtr] = 0;
+ ctx->segmentPtr = 0;
+ ctx->subpathCount++;
+ ctx->simpleConvex = false;
+}
+// clear path datas in context
+void _clear_path(VkvgContext ctx) {
+ ctx->pathPtr = 0;
+ ctx->pathes[ctx->pathPtr] = 0;
+ ctx->pointCount = 0;
+ ctx->segmentPtr = 0;
+ ctx->subpathCount = 0;
+ ctx->simpleConvex = false;
+}
+void _remove_last_point(VkvgContext ctx) {
+ ctx->pathes[ctx->pathPtr]--;
+ ctx->pointCount--;
+ if (ctx->segmentPtr > 0) { // if path is segmented
+ if (!ctx->pathes[ctx->pathPtr + ctx->segmentPtr]) // if current segment is empty
+ ctx->segmentPtr--;
+ ctx->pathes[ctx->pathPtr + ctx->segmentPtr]--; // decrement last segment point count
+ if ((ctx->pathes[ctx->pathPtr + ctx->segmentPtr] & PATH_ELT_MASK) == 0) // if no point left (was only one)
+ ctx->pathes[ctx->pathPtr + ctx->segmentPtr] = 0; // reset current segment
+ else if (ctx->pathes[ctx->pathPtr + ctx->segmentPtr] & PATH_HAS_CURVES_BIT) // if segment is a curve
+ ctx->segmentPtr++; // then segPtr has to be forwarded to new segment
+ }
+}
+bool _path_is_closed(VkvgContext ctx, uint32_t ptrPath) { return ctx->pathes[ptrPath] & PATH_CLOSED_BIT; }
+void _add_point(VkvgContext ctx, float x, float y) {
+ if (_check_point_array(ctx))
+ return;
+ if (isnan(x) || isnan(y)) {
+ LOG(VKVG_LOG_DEBUG, "_add_point: (%f, %f)\n", x, y);
+ return;
+ }
+ vec2 v = {x, y};
+ /*if (!_current_path_is_empty(ctx) && vec2_length(vec2_sub(ctx->points[ctx->pointCount-1], v))<1.f)
+ return;*/
+ LOG(VKVG_LOG_INFO_PTS, "_add_point: (%f, %f)\n", x, y);
+
+ ctx->points[ctx->pointCount] = v;
+ ctx->pointCount++; // total point count of pathes, (for array bounds check)
+ ctx->pathes[ctx->pathPtr]++; // total point count in path
+ if (ctx->segmentPtr > 0)
+ ctx->pathes[ctx->pathPtr + ctx->segmentPtr]++; // total point count in path's segment
+}
+float _normalizeAngle(float a) {
+ float res = ROUND_DOWN(fmodf(a, 2.0f * M_PIF), 100);
+ if (res < 0.0f)
+ res += 2.0f * M_PIF;
+ return res;
+}
+float _get_arc_step(VkvgContext ctx, float radius) {
+ float sx, sy;
+ vkvg_matrix_get_scale(&ctx->pushConsts.mat, &sx, &sy);
+ float r = radius * fabsf(fmaxf(sx, sy));
+ if (r < 30.0f)
+ return fminf(M_PIF / 3.f, M_PIF / r);
+ return fminf(M_PIF / 3.f, M_PIF / (r * 0.4f));
+}
+void _create_gradient_buff(VkvgContext ctx) {
+ vkh_buffer_init((VkhDevice)ctx->dev, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU,
+ sizeof(vkvg_gradient_t), &ctx->uboGrad, true);
+}
+void _create_vertices_buff(VkvgContext ctx) {
+ vkh_buffer_init((VkhDevice)ctx->dev, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU,
+ ctx->sizeVBO * sizeof(Vertex), &ctx->vertices, true);
+ vkh_buffer_init((VkhDevice)ctx->dev, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU,
+ ctx->sizeIBO * sizeof(VKVG_IBO_INDEX_TYPE), &ctx->indices, true);
+}
+void _resize_vbo(VkvgContext ctx, uint32_t new_size) {
+ if (!_wait_ctx_flush_end(ctx)) // wait previous cmd if not completed
+ return;
+ LOG(VKVG_LOG_DBG_ARRAYS, "resize VBO: %d -> ", ctx->sizeVBO);
+ ctx->sizeVBO = new_size;
+ uint32_t mod = ctx->sizeVBO % VKVG_VBO_SIZE;
+ if (mod > 0)
+ ctx->sizeVBO += VKVG_VBO_SIZE - mod;
+ LOG(VKVG_LOG_DBG_ARRAYS, "%d\n", ctx->sizeVBO);
+ vkh_buffer_resize(&ctx->vertices, ctx->sizeVBO * sizeof(Vertex), true);
+}
+void _resize_ibo(VkvgContext ctx, size_t new_size) {
+ if (!_wait_ctx_flush_end(ctx)) // wait previous cmd if not completed
+ return;
+ ctx->sizeIBO = new_size;
+ uint32_t mod = ctx->sizeIBO % VKVG_IBO_SIZE;
+ if (mod > 0)
+ ctx->sizeIBO += VKVG_IBO_SIZE - mod;
+ LOG(VKVG_LOG_DBG_ARRAYS, "resize IBO: new size: %d\n", ctx->sizeIBO);
+ vkh_buffer_resize(&ctx->indices, ctx->sizeIBO * sizeof(VKVG_IBO_INDEX_TYPE), true);
+}
+void _add_vertexf(VkvgContext ctx, float x, float y) {
+ Vertex *pVert = &ctx->vertexCache[ctx->vertCount];
+ pVert->pos.x = x;
+ pVert->pos.y = y;
+ pVert->color = ctx->curColor;
+ pVert->uv.z = -1;
+ LOG(VKVG_LOG_INFO_VBO, "Add Vertexf %10d: pos:(%10.4f, %10.4f) uv:(%10.4f,%10.4f,%10.4f) color:0x%.8x \n",
+ ctx->vertCount, pVert->pos.x, pVert->pos.y, pVert->uv.x, pVert->uv.y, pVert->uv.z, pVert->color);
+ ctx->vertCount++;
+ _check_vertex_cache_size(ctx);
+}
+void _add_vertexf_unchecked(VkvgContext ctx, float x, float y) {
+ Vertex *pVert = &ctx->vertexCache[ctx->vertCount];
+ pVert->pos.x = x;
+ pVert->pos.y = y;
+ pVert->color = ctx->curColor;
+ pVert->uv.z = -1;
+ LOG(VKVG_LOG_INFO_VBO, "Add Vertexf %10d: pos:(%10.4f, %10.4f) uv:(%10.4f,%10.4f,%10.4f) color:0x%.8x \n",
+ ctx->vertCount, pVert->pos.x, pVert->pos.y, pVert->uv.x, pVert->uv.y, pVert->uv.z, pVert->color);
+ ctx->vertCount++;
+}
+void _add_vertex(VkvgContext ctx, Vertex v) {
+ ctx->vertexCache[ctx->vertCount] = v;
+ LOG(VKVG_LOG_INFO_VBO, "Add Vertex %10d: pos:(%10.4f, %10.4f) uv:(%10.4f,%10.4f,%10.4f) color:0x%.8x \n",
+ ctx->vertCount, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.uv.z, v.color);
+ ctx->vertCount++;
+ _check_vertex_cache_size(ctx);
+}
+void _set_vertex(VkvgContext ctx, uint32_t idx, Vertex v) { ctx->vertexCache[idx] = v; }
#ifdef VKVG_FILL_NZ_GLUTESS
-void _add_indice (VkvgContext ctx, VKVG_IBO_INDEX_TYPE i) {
- ctx->indexCache[ctx->indCount++] = i;
- _check_index_cache_size(ctx);
-}
-void _add_indice_for_fan (VkvgContext ctx, VKVG_IBO_INDEX_TYPE i) {
- VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount];
- inds[0] = ctx->tesselator_fan_start;
- inds[1] = ctx->indexCache[ctx->indCount-1];
- inds[2] = i;
- ctx->indCount+=3;
- _check_index_cache_size(ctx);
-}
-void _add_indice_for_strip (VkvgContext ctx, VKVG_IBO_INDEX_TYPE i, bool odd) {
- VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount];
- if (odd) {
- inds[0] = ctx->indexCache[ctx->indCount-2];
- inds[1] = i;
- inds[2] = ctx->indexCache[ctx->indCount-1];
- } else {
- inds[0] = ctx->indexCache[ctx->indCount-1];
- inds[1] = ctx->indexCache[ctx->indCount-2];
- inds[2] = i;
- }
- ctx->indCount+=3;
- _check_index_cache_size(ctx);
+void _add_indice(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i) {
+ ctx->indexCache[ctx->indCount++] = i;
+ _check_index_cache_size(ctx);
+}
+void _add_indice_for_fan(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i) {
+ VKVG_IBO_INDEX_TYPE *inds = &ctx->indexCache[ctx->indCount];
+ inds[0] = ctx->tesselator_fan_start;
+ inds[1] = ctx->indexCache[ctx->indCount - 1];
+ inds[2] = i;
+ ctx->indCount += 3;
+ _check_index_cache_size(ctx);
+}
+void _add_indice_for_strip(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i, bool odd) {
+ VKVG_IBO_INDEX_TYPE *inds = &ctx->indexCache[ctx->indCount];
+ if (odd) {
+ inds[0] = ctx->indexCache[ctx->indCount - 2];
+ inds[1] = i;
+ inds[2] = ctx->indexCache[ctx->indCount - 1];
+ } else {
+ inds[0] = ctx->indexCache[ctx->indCount - 1];
+ inds[1] = ctx->indexCache[ctx->indCount - 2];
+ inds[2] = i;
+ }
+ ctx->indCount += 3;
+ _check_index_cache_size(ctx);
}
#endif
-void _add_tri_indices_for_rect (VkvgContext ctx, VKVG_IBO_INDEX_TYPE i){
- VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount];
- inds[0] = i;
- inds[1] = i+2;
- inds[2] = i+1;
- inds[3] = i+1;
- inds[4] = i+2;
- inds[5] = i+3;
- ctx->indCount+=6;
-
- _check_index_cache_size(ctx);
- LOG(VKVG_LOG_INFO_IBO, "Rectangle IDX: %d %d %d | %d %d %d (count=%d)\n", inds[0], inds[1], inds[2], inds[3], inds[4], inds[5], ctx->indCount);
-}
-void _add_triangle_indices(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i0, VKVG_IBO_INDEX_TYPE i1, VKVG_IBO_INDEX_TYPE i2){
- VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount];
- inds[0] = i0;
- inds[1] = i1;
- inds[2] = i2;
- ctx->indCount+=3;
-
- _check_index_cache_size(ctx);
- LOG(VKVG_LOG_INFO_IBO, "Triangle IDX: %d %d %d (indCount=%d)\n", i0,i1,i2,ctx->indCount);
-}
-void _add_triangle_indices_unchecked (VkvgContext ctx, VKVG_IBO_INDEX_TYPE i0, VKVG_IBO_INDEX_TYPE i1, VKVG_IBO_INDEX_TYPE i2){
- VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount];
- inds[0] = i0;
- inds[1] = i1;
- inds[2] = i2;
- ctx->indCount+=3;
-
- LOG(VKVG_LOG_INFO_IBO, "Triangle IDX: %d %d %d (indCount=%d)\n", i0,i1,i2,ctx->indCount);
-}
-void _vao_add_rectangle (VkvgContext ctx, float x, float y, float width, float height){
- Vertex v[4] =
- {
- {{x,y}, ctx->curColor, {0,0,-1}},
- {{x,y+height}, ctx->curColor, {0,0,-1}},
- {{x+width,y}, ctx->curColor, {0,0,-1}},
- {{x+width,y+height},ctx->curColor, {0,0,-1}}
- };
- VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
- Vertex* pVert = &ctx->vertexCache[ctx->vertCount];
- memcpy (pVert,v,4*sizeof(Vertex));
- ctx->vertCount+=4;
-
- _check_vertex_cache_size(ctx);
-
- _add_tri_indices_for_rect(ctx, firstIdx);
-}
-//start render pass if not yet started or update push const if requested
-void _ensure_renderpass_is_started (VkvgContext ctx) {
- LOG(VKVG_LOG_INFO, "_ensure_renderpass_is_started\n");
- if (!ctx->cmdStarted)
- _start_cmd_for_render_pass(ctx);
- else if (ctx->pushCstDirty)
- _update_push_constants(ctx);
-}
-void _create_cmd_buff (VkvgContext ctx){
- vkh_cmd_buffs_create((VkhDevice)ctx->dev, ctx->cmdPool,VK_COMMAND_BUFFER_LEVEL_PRIMARY, 2, ctx->cmdBuffers);
+void _add_tri_indices_for_rect(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i) {
+ VKVG_IBO_INDEX_TYPE *inds = &ctx->indexCache[ctx->indCount];
+ inds[0] = i;
+ inds[1] = i + 2;
+ inds[2] = i + 1;
+ inds[3] = i + 1;
+ inds[4] = i + 2;
+ inds[5] = i + 3;
+ ctx->indCount += 6;
+
+ _check_index_cache_size(ctx);
+ LOG(VKVG_LOG_INFO_IBO, "Rectangle IDX: %d %d %d | %d %d %d (count=%d)\n", inds[0], inds[1], inds[2], inds[3],
+ inds[4], inds[5], ctx->indCount);
+}
+void _add_triangle_indices(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i0, VKVG_IBO_INDEX_TYPE i1, VKVG_IBO_INDEX_TYPE i2) {
+ VKVG_IBO_INDEX_TYPE *inds = &ctx->indexCache[ctx->indCount];
+ inds[0] = i0;
+ inds[1] = i1;
+ inds[2] = i2;
+ ctx->indCount += 3;
+
+ _check_index_cache_size(ctx);
+ LOG(VKVG_LOG_INFO_IBO, "Triangle IDX: %d %d %d (indCount=%d)\n", i0, i1, i2, ctx->indCount);
+}
+void _add_triangle_indices_unchecked(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i0, VKVG_IBO_INDEX_TYPE i1,
+ VKVG_IBO_INDEX_TYPE i2) {
+ VKVG_IBO_INDEX_TYPE *inds = &ctx->indexCache[ctx->indCount];
+ inds[0] = i0;
+ inds[1] = i1;
+ inds[2] = i2;
+ ctx->indCount += 3;
+
+ LOG(VKVG_LOG_INFO_IBO, "Triangle IDX: %d %d %d (indCount=%d)\n", i0, i1, i2, ctx->indCount);
+}
+void _vao_add_rectangle(VkvgContext ctx, float x, float y, float width, float height) {
+ Vertex v[4] = {{{x, y}, ctx->curColor, {0, 0, -1}},
+ {{x, y + height}, ctx->curColor, {0, 0, -1}},
+ {{x + width, y}, ctx->curColor, {0, 0, -1}},
+ {{x + width, y + height}, ctx->curColor, {0, 0, -1}}};
+ VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+ Vertex *pVert = &ctx->vertexCache[ctx->vertCount];
+ memcpy(pVert, v, 4 * sizeof(Vertex));
+ ctx->vertCount += 4;
+
+ _check_vertex_cache_size(ctx);
+
+ _add_tri_indices_for_rect(ctx, firstIdx);
+}
+// start render pass if not yet started or update push const if requested
+void _ensure_renderpass_is_started(VkvgContext ctx) {
+ LOG(VKVG_LOG_INFO, "_ensure_renderpass_is_started\n");
+ if (!ctx->cmdStarted)
+ _start_cmd_for_render_pass(ctx);
+ else if (ctx->pushCstDirty)
+ _update_push_constants(ctx);
+}
+void _create_cmd_buff(VkvgContext ctx) {
+ vkh_cmd_buffs_create((VkhDevice)ctx->dev, ctx->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 2, ctx->cmdBuffers);
#if defined(DEBUG) && defined(ENABLE_VALIDATION)
- vkh_device_set_object_name((VkhDevice)ctx->pSurf->dev, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)ctx->cmd, "vkvgCtxCmd");
+ vkh_device_set_object_name((VkhDevice)ctx->pSurf->dev, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+ (uint64_t)ctx->cmd, "vkvgCtxCmd");
#endif
}
-void _clear_attachment (VkvgContext ctx) {
-
-}
+void _clear_attachment(VkvgContext ctx) {}
-bool _wait_ctx_flush_end (VkvgContext ctx) {
- LOG(VKVG_LOG_INFO, "CTX: _wait_flush_fence\n");
+bool _wait_ctx_flush_end(VkvgContext ctx) {
+ LOG(VKVG_LOG_INFO, "CTX: _wait_flush_fence\n");
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- if (vkh_timeline_wait ((VkhDevice)ctx->dev, ctx->pSurf->timeline, ctx->timelineStep) == VK_SUCCESS)
- return true;
+ if (vkh_timeline_wait((VkhDevice)ctx->dev, ctx->pSurf->timeline, ctx->timelineStep) == VK_SUCCESS)
+ return true;
#else
- if (WaitForFences (ctx->dev->vkDev, 1, &ctx->flushFence, VK_TRUE, VKVG_FENCE_TIMEOUT) == VK_SUCCESS)
- return true;
+ if (WaitForFences(ctx->dev->vkDev, 1, &ctx->flushFence, VK_TRUE, VKVG_FENCE_TIMEOUT) == VK_SUCCESS)
+ return true;
#endif
- LOG(VKVG_LOG_DEBUG, "CTX: _wait_flush_fence timeout\n");
- ctx->status = VKVG_STATUS_TIMEOUT;
- return false;
+ LOG(VKVG_LOG_DEBUG, "CTX: _wait_flush_fence timeout\n");
+ ctx->status = VKVG_STATUS_TIMEOUT;
+ return false;
}
+bool _wait_and_submit_cmd(VkvgContext ctx) {
+ if (!ctx->cmdStarted) // current cmd buff is empty, be aware that wait is also canceled!!
+ return true;
-bool _wait_and_submit_cmd (VkvgContext ctx){
- if (!ctx->cmdStarted)//current cmd buff is empty, be aware that wait is also canceled!!
- return true;
-
- LOG(VKVG_LOG_INFO, "CTX: _wait_and_submit_cmd\n");
+ LOG(VKVG_LOG_INFO, "CTX: _wait_and_submit_cmd\n");
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- VkvgSurface surf = ctx->pSurf;
- VkvgDevice dev = surf->dev;
- //vkh_timeline_wait ((VkhDevice)dev, surf->timeline, ct->timelineStep);
- if (ctx->pattern && ctx->pattern->type == VKVG_PATTERN_TYPE_SURFACE) {
- //add source surface timeline sync.
- VkvgSurface source = (VkvgSurface)ctx->pattern->data;
- LOCK_SURFACE(surf)
- LOCK_SURFACE(source)
- LOCK_DEVICE
- vkh_cmd_submit_timelined2 (dev->gQueue, &ctx->cmd,
- (VkSemaphore[2]){surf->timeline,source->timeline},
- (uint64_t[2]){surf->timelineStep,source->timelineStep},
- (uint64_t[2]){surf->timelineStep+1,source->timelineStep+1});
- surf->timelineStep++;
- source->timelineStep++;
- ctx->timelineStep = surf->timelineStep;
- UNLOCK_DEVICE
- UNLOCK_SURFACE(source)
- UNLOCK_SURFACE(surf)
- } else {
- LOCK_SURFACE(surf)
- LOCK_DEVICE
- vkh_cmd_submit_timelined (dev->gQueue, &ctx->cmd, surf->timeline, surf->timelineStep, surf->timelineStep+1);
- surf->timelineStep++;
- ctx->timelineStep = surf->timelineStep;
- UNLOCK_DEVICE
- UNLOCK_SURFACE(surf)
- }
+ VkvgSurface surf = ctx->pSurf;
+ VkvgDevice dev = surf->dev;
+ // vkh_timeline_wait ((VkhDevice)dev, surf->timeline, ct->timelineStep);
+ if (ctx->pattern && ctx->pattern->type == VKVG_PATTERN_TYPE_SURFACE) {
+ // add source surface timeline sync.
+ VkvgSurface source = (VkvgSurface)ctx->pattern->data;
+ LOCK_SURFACE(surf)
+ LOCK_SURFACE(source)
+ LOCK_DEVICE
+ vkh_cmd_submit_timelined2(dev->gQueue, &ctx->cmd, (VkSemaphore[2]){surf->timeline, source->timeline},
+ (uint64_t[2]){surf->timelineStep, source->timelineStep},
+ (uint64_t[2]){surf->timelineStep + 1, source->timelineStep + 1});
+ surf->timelineStep++;
+ source->timelineStep++;
+ ctx->timelineStep = surf->timelineStep;
+ UNLOCK_DEVICE
+ UNLOCK_SURFACE(source)
+ UNLOCK_SURFACE(surf)
+ } else {
+ LOCK_SURFACE(surf)
+ LOCK_DEVICE
+ vkh_cmd_submit_timelined(dev->gQueue, &ctx->cmd, surf->timeline, surf->timelineStep, surf->timelineStep + 1);
+ surf->timelineStep++;
+ ctx->timelineStep = surf->timelineStep;
+ UNLOCK_DEVICE
+ UNLOCK_SURFACE(surf)
+ }
#else
- if (!_wait_ctx_flush_end (ctx))
- return false;
- ResetFences (ctx->dev->vkDev, 1, &ctx->flushFence);
- _device_submit_cmd (ctx->dev, &ctx->cmd, ctx->flushFence);
+ if (!_wait_ctx_flush_end(ctx))
+ return false;
+ ResetFences(ctx->dev->vkDev, 1, &ctx->flushFence);
+ _device_submit_cmd(ctx->dev, &ctx->cmd, ctx->flushFence);
#endif
- if (ctx->cmd == ctx->cmdBuffers[0])
- ctx->cmd = ctx->cmdBuffers[1];
- else
- ctx->cmd = ctx->cmdBuffers[0];
-
- ResetCommandBuffer (ctx->cmd, 0);
- ctx->cmdStarted = false;
- return true;
-}
-/*void _explicit_ms_resolve (VkvgContext ctx){//should init cmd before calling this (unused, using automatic resolve by renderpass)
- vkh_image_set_layout (ctx->cmd, ctx->pSurf->imgMS, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkh_image_set_layout (ctx->cmd, ctx->pSurf->img, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
-
- VkImageResolve re = {
- .extent = {ctx->pSurf->width, ctx->pSurf->height,1},
- .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT,0,0,1},
- .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT,0,0,1}
- };
-
- vkCmdResolveImage(ctx->cmd,
- vkh_image_get_vkimage (ctx->pSurf->imgMS), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- vkh_image_get_vkimage (ctx->pSurf->img) ,VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1,&re);
- vkh_image_set_layout (ctx->cmd, ctx->pSurf->imgMS, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ,
- VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+ if (ctx->cmd == ctx->cmdBuffers[0])
+ ctx->cmd = ctx->cmdBuffers[1];
+ else
+ ctx->cmd = ctx->cmdBuffers[0];
+
+ ResetCommandBuffer(ctx->cmd, 0);
+ ctx->cmdStarted = false;
+ return true;
+}
+/*void _explicit_ms_resolve (VkvgContext ctx){//should init cmd before calling this (unused, using automatic resolve by
+renderpass) vkh_image_set_layout (ctx->cmd, ctx->pSurf->imgMS, VK_IMAGE_ASPECT_COLOR_BIT,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout (ctx->cmd, ctx->pSurf->img, VK_IMAGE_ASPECT_COLOR_BIT,
+ VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ VkImageResolve re = {
+ .extent = {ctx->pSurf->width, ctx->pSurf->height,1},
+ .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT,0,0,1},
+ .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT,0,0,1}
+ };
+
+ vkCmdResolveImage(ctx->cmd,
+ vkh_image_get_vkimage (ctx->pSurf->imgMS), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vkh_image_get_vkimage (ctx->pSurf->img) ,VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ 1,&re);
+ vkh_image_set_layout (ctx->cmd, ctx->pSurf->imgMS, VK_IMAGE_ASPECT_COLOR_BIT,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}*/
-//pre flush vertices because of vbo or ibo too small, all vertices except last draw call are flushed
-//this function expects a vertex offset > 0
-void _flush_vertices_caches_until_vertex_base (VkvgContext ctx) {
- _wait_ctx_flush_end (ctx);
-
- memcpy(vkh_buffer_get_mapped_pointer(&ctx->vertices), ctx->vertexCache, ctx->curVertOffset * sizeof (Vertex));
- memcpy(vkh_buffer_get_mapped_pointer(&ctx->indices), ctx->indexCache, ctx->curIndStart * sizeof (VKVG_IBO_INDEX_TYPE));
-
- //copy remaining vertices and indices to caches starts
- //this could be optimized at the cost of additional offsets.
- ctx->vertCount -= ctx->curVertOffset;
- ctx->indCount -= ctx->curIndStart;
- memcpy(ctx->vertexCache, &ctx->vertexCache[ctx->curVertOffset], ctx->vertCount * sizeof (Vertex));
- memcpy(ctx->indexCache, &ctx->indexCache[ctx->curIndStart], ctx->indCount * sizeof (VKVG_IBO_INDEX_TYPE));
-
- ctx->curVertOffset = 0;
- ctx->curIndStart = 0;
-}
-//copy vertex and index caches to the vbo and ibo vkbuffers used by gpu for drawing
-//current running cmd has to be completed to free usage of those
-void _flush_vertices_caches (VkvgContext ctx) {
- if (!_wait_ctx_flush_end (ctx))
- return;
-
- memcpy(vkh_buffer_get_mapped_pointer(&ctx->vertices), ctx->vertexCache, ctx->vertCount * sizeof (Vertex));
- memcpy(vkh_buffer_get_mapped_pointer(&ctx->indices), ctx->indexCache, ctx->indCount * sizeof (VKVG_IBO_INDEX_TYPE));
-
- ctx->vertCount = ctx->indCount = ctx->curIndStart = ctx->curVertOffset = 0;
-}
-//this func expect cmdStarted to be true
-void _end_render_pass (VkvgContext ctx) {
- LOG(VKVG_LOG_INFO, "END RENDER PASS: ctx = %p;\n", ctx);
- CmdEndRenderPass (ctx->cmd);
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_end (ctx->cmd);
+// pre flush vertices because of vbo or ibo too small, all vertices except last draw call are flushed
+// this function expects a vertex offset > 0
+void _flush_vertices_caches_until_vertex_base(VkvgContext ctx) {
+ _wait_ctx_flush_end(ctx);
+
+ memcpy(vkh_buffer_get_mapped_pointer(&ctx->vertices), ctx->vertexCache, ctx->curVertOffset * sizeof(Vertex));
+ memcpy(vkh_buffer_get_mapped_pointer(&ctx->indices), ctx->indexCache,
+ ctx->curIndStart * sizeof(VKVG_IBO_INDEX_TYPE));
+
+ // copy remaining vertices and indices to caches starts
+ // this could be optimized at the cost of additional offsets.
+ ctx->vertCount -= ctx->curVertOffset;
+ ctx->indCount -= ctx->curIndStart;
+ memcpy(ctx->vertexCache, &ctx->vertexCache[ctx->curVertOffset], ctx->vertCount * sizeof(Vertex));
+ memcpy(ctx->indexCache, &ctx->indexCache[ctx->curIndStart], ctx->indCount * sizeof(VKVG_IBO_INDEX_TYPE));
+
+ ctx->curVertOffset = 0;
+ ctx->curIndStart = 0;
+}
+// copy vertex and index caches to the vbo and ibo vkbuffers used by gpu for drawing
+// current running cmd has to be completed to free usage of those
+void _flush_vertices_caches(VkvgContext ctx) {
+ if (!_wait_ctx_flush_end(ctx))
+ return;
+
+ memcpy(vkh_buffer_get_mapped_pointer(&ctx->vertices), ctx->vertexCache, ctx->vertCount * sizeof(Vertex));
+ memcpy(vkh_buffer_get_mapped_pointer(&ctx->indices), ctx->indexCache, ctx->indCount * sizeof(VKVG_IBO_INDEX_TYPE));
+
+ ctx->vertCount = ctx->indCount = ctx->curIndStart = ctx->curVertOffset = 0;
+}
+// this func expect cmdStarted to be true
+void _end_render_pass(VkvgContext ctx) {
+ LOG(VKVG_LOG_INFO, "END RENDER PASS: ctx = %p;\n", ctx);
+ CmdEndRenderPass(ctx->cmd);
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_end(ctx->cmd);
#endif
- ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass;
+ ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass;
}
-void _check_vao_size (VkvgContext ctx) {
- if (ctx->vertCount > ctx->sizeVBO || ctx->indCount > ctx->sizeIBO){
- //vbo or ibo buffers too small
- if (ctx->cmdStarted)
- //if cmd is started buffers, are already bound, so no resize is possible
- //instead we flush, and clear vbo and ibo caches
- _flush_cmd_until_vx_base (ctx);
- if (ctx->vertCount > ctx->sizeVBO)
- _resize_vbo(ctx, ctx->sizeVertices);
- if (ctx->indCount > ctx->sizeIBO)
- _resize_ibo(ctx, ctx->sizeIndices);
- }
+void _check_vao_size(VkvgContext ctx) {
+ if (ctx->vertCount > ctx->sizeVBO || ctx->indCount > ctx->sizeIBO) {
+ // vbo or ibo buffers too small
+ if (ctx->cmdStarted)
+ // if cmd is started buffers, are already bound, so no resize is possible
+ // instead we flush, and clear vbo and ibo caches
+ _flush_cmd_until_vx_base(ctx);
+ if (ctx->vertCount > ctx->sizeVBO)
+ _resize_vbo(ctx, ctx->sizeVertices);
+ if (ctx->indCount > ctx->sizeIBO)
+ _resize_ibo(ctx, ctx->sizeIndices);
+ }
}
-//stroke and non-zero draw call for solid color flush
-void _emit_draw_cmd_undrawn_vertices (VkvgContext ctx){
- if (ctx->indCount == ctx->curIndStart)
- return;
+// stroke and non-zero draw call for solid color flush
+void _emit_draw_cmd_undrawn_vertices(VkvgContext ctx) {
+ if (ctx->indCount == ctx->curIndStart)
+ return;
- _check_vao_size (ctx);
+ _check_vao_size(ctx);
- _ensure_renderpass_is_started (ctx);
+ _ensure_renderpass_is_started(ctx);
#ifdef VKVG_WIRED_DEBUG
- if (vkvg_wired_debug&vkvg_wired_debug_mode_normal)
- CmdDrawIndexed(ctx->cmd, ctx->indCount - ctx->curIndStart, 1, ctx->curIndStart, (int32_t)ctx->curVertOffset, 0);
- if (vkvg_wired_debug&vkvg_wired_debug_mode_lines) {
- CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineLineList);
- CmdDrawIndexed(ctx->cmd, ctx->indCount - ctx->curIndStart, 1, ctx->curIndStart, (int32_t)ctx->curVertOffset, 0);
- }
- if (vkvg_wired_debug&vkvg_wired_debug_mode_points) {
- CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineWired);
- CmdDrawIndexed(ctx->cmd, ctx->indCount - ctx->curIndStart, 1, ctx->curIndStart, (int32_t)ctx->curVertOffset, 0);
- }
- if (vkvg_wired_debug&vkvg_wired_debug_mode_both)
- CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipe_OVER);
+ if (vkvg_wired_debug & vkvg_wired_debug_mode_normal)
+ CmdDrawIndexed(ctx->cmd, ctx->indCount - ctx->curIndStart, 1, ctx->curIndStart, (int32_t)ctx->curVertOffset, 0);
+ if (vkvg_wired_debug & vkvg_wired_debug_mode_lines) {
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineLineList);
+ CmdDrawIndexed(ctx->cmd, ctx->indCount - ctx->curIndStart, 1, ctx->curIndStart, (int32_t)ctx->curVertOffset, 0);
+ }
+ if (vkvg_wired_debug & vkvg_wired_debug_mode_points) {
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineWired);
+ CmdDrawIndexed(ctx->cmd, ctx->indCount - ctx->curIndStart, 1, ctx->curIndStart, (int32_t)ctx->curVertOffset, 0);
+ }
+ if (vkvg_wired_debug & vkvg_wired_debug_mode_both)
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipe_OVER);
#else
- CmdDrawIndexed(ctx->cmd, ctx->indCount - ctx->curIndStart, 1, ctx->curIndStart, (int32_t)ctx->curVertOffset, 0);
+ CmdDrawIndexed(ctx->cmd, ctx->indCount - ctx->curIndStart, 1, ctx->curIndStart, (int32_t)ctx->curVertOffset, 0);
#endif
- LOG(VKVG_LOG_INFO, "RECORD DRAW CMD: ctx = %p; vertices = %d; indices = %d (vxOff = %d idxStart = %d idxTot = %d )\n",
- ctx, ctx->vertCount - ctx->curVertOffset,
- ctx->indCount - ctx->curIndStart, ctx->curVertOffset, ctx->curIndStart, ctx->indCount);
-
- ctx->curIndStart = ctx->indCount;
- ctx->curVertOffset = ctx->vertCount;
-}
-//preflush vertices with drawcommand already emited
-void _flush_cmd_until_vx_base (VkvgContext ctx){
- _end_render_pass (ctx);
- if (ctx->curVertOffset > 0){
- LOG(VKVG_LOG_INFO, "FLUSH UNTIL VX BASE CTX: ctx = %p; vertices = %d; indices = %d\n", ctx, ctx->vertCount, ctx->indCount);
- _flush_vertices_caches_until_vertex_base (ctx);
- }
- vkh_cmd_end (ctx->cmd);
- _wait_and_submit_cmd (ctx);
-}
-void _flush_cmd_buff (VkvgContext ctx){
- _emit_draw_cmd_undrawn_vertices (ctx);
- if (!ctx->cmdStarted)
- return;
- _end_render_pass (ctx);
- LOG(VKVG_LOG_INFO, "FLUSH CTX: ctx = %p; vertices = %d; indices = %d\n", ctx, ctx->vertCount, ctx->indCount);
- _flush_vertices_caches (ctx);
- vkh_cmd_end (ctx->cmd);
-
- _wait_and_submit_cmd (ctx);
-}
-
-//bind correct draw pipeline depending on current OPERATOR
-void _bind_draw_pipeline (VkvgContext ctx) {
- switch (ctx->curOperator) {
- case VKVG_OPERATOR_OVER:
- CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipe_OVER);
- break;
- case VKVG_OPERATOR_CLEAR:
- CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipe_CLEAR);
- break;
- case VKVG_OPERATOR_DIFFERENCE:
- CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipe_SUB);
- break;
- default:
- CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipe_OVER);
- break;
- }
-}
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
-const float DBG_LAB_COLOR_RP[4] = {0,0,1,1};
-const float DBG_LAB_COLOR_FSQ[4] = {1,0,0,1};
+ LOG(VKVG_LOG_INFO,
+ "RECORD DRAW CMD: ctx = %p; vertices = %d; indices = %d (vxOff = %d idxStart = %d idxTot = %d )\n", ctx,
+ ctx->vertCount - ctx->curVertOffset, ctx->indCount - ctx->curIndStart, ctx->curVertOffset, ctx->curIndStart,
+ ctx->indCount);
+
+ ctx->curIndStart = ctx->indCount;
+ ctx->curVertOffset = ctx->vertCount;
+}
+// preflush vertices with drawcommand already emited
+void _flush_cmd_until_vx_base(VkvgContext ctx) {
+ _end_render_pass(ctx);
+ if (ctx->curVertOffset > 0) {
+ LOG(VKVG_LOG_INFO, "FLUSH UNTIL VX BASE CTX: ctx = %p; vertices = %d; indices = %d\n", ctx, ctx->vertCount,
+ ctx->indCount);
+ _flush_vertices_caches_until_vertex_base(ctx);
+ }
+ vkh_cmd_end(ctx->cmd);
+ _wait_and_submit_cmd(ctx);
+}
+void _flush_cmd_buff(VkvgContext ctx) {
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ if (!ctx->cmdStarted)
+ return;
+ _end_render_pass(ctx);
+ LOG(VKVG_LOG_INFO, "FLUSH CTX: ctx = %p; vertices = %d; indices = %d\n", ctx, ctx->vertCount, ctx->indCount);
+ _flush_vertices_caches(ctx);
+ vkh_cmd_end(ctx->cmd);
+
+ _wait_and_submit_cmd(ctx);
+}
+
+// bind correct draw pipeline depending on current OPERATOR
+void _bind_draw_pipeline(VkvgContext ctx) {
+ switch (ctx->curOperator) {
+ case VKVG_OPERATOR_OVER:
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipe_OVER);
+ break;
+ case VKVG_OPERATOR_CLEAR:
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipe_CLEAR);
+ break;
+ case VKVG_OPERATOR_DIFFERENCE:
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipe_SUB);
+ break;
+ default:
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipe_OVER);
+ break;
+ }
+}
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+const float DBG_LAB_COLOR_RP[4] = {0, 0, 1, 1};
+const float DBG_LAB_COLOR_FSQ[4] = {1, 0, 0, 1};
#endif
-void _start_cmd_for_render_pass (VkvgContext ctx) {
- LOG(VKVG_LOG_INFO, "START RENDER PASS: ctx = %p\n", ctx);
- vkh_cmd_begin (ctx->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
-
- if (ctx->pSurf->img->layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || ctx->dev->threadAware){
- VkhImage imgMs = ctx->pSurf->imgMS;
- if (imgMs != NULL)
- vkh_image_set_layout(ctx->cmd, imgMs, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
-
- vkh_image_set_layout(ctx->cmd, ctx->pSurf->img, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
- vkh_image_set_layout (ctx->cmd, ctx->pSurf->stencil, ctx->dev->stencilAspectFlag,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
- }
-
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_start(ctx->cmd, "ctx render pass", DBG_LAB_COLOR_RP);
+void _start_cmd_for_render_pass(VkvgContext ctx) {
+ LOG(VKVG_LOG_INFO, "START RENDER PASS: ctx = %p\n", ctx);
+ vkh_cmd_begin(ctx->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+
+ if (ctx->pSurf->img->layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || ctx->dev->threadAware) {
+ VkhImage imgMs = ctx->pSurf->imgMS;
+ if (imgMs != NULL)
+ vkh_image_set_layout(ctx->cmd, imgMs, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+
+ vkh_image_set_layout(ctx->cmd, ctx->pSurf->img, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+ vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, ctx->dev->stencilAspectFlag,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
+ }
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_start(ctx->cmd, "ctx render pass", DBG_LAB_COLOR_RP);
#endif
- CmdBeginRenderPass (ctx->cmd, &ctx->renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
- VkViewport viewport = {0,0,(float)ctx->pSurf->width,(float)ctx->pSurf->height,0,1.f};
- CmdSetViewport(ctx->cmd, 0, 1, &viewport);
-
- CmdSetScissor(ctx->cmd, 0, 1, &ctx->bounds);
-
- VkDescriptorSet dss[] = {ctx->dsFont, ctx->dsSrc,ctx->dsGrad};
- CmdBindDescriptorSets(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelineLayout,
- 0, 3, dss, 0, NULL);
-
- VkDeviceSize offsets[1] = { 0 };
- CmdBindVertexBuffers(ctx->cmd, 0, 1, &ctx->vertices.buffer, offsets);
- CmdBindIndexBuffer(ctx->cmd, ctx->indices.buffer, 0, VKVG_VK_INDEX_TYPE);
-
- _update_push_constants (ctx);
-
- _bind_draw_pipeline (ctx);
- CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
- ctx->cmdStarted = true;
-}
-//compute inverse mat used in shader when context matrix has changed
-//then trigger push constants command
-void _set_mat_inv_and_vkCmdPush (VkvgContext ctx) {
- ctx->pushConsts.matInv = ctx->pushConsts.mat;
- vkvg_matrix_invert (&ctx->pushConsts.matInv);
- ctx->pushCstDirty = true;
-}
-void _update_push_constants (VkvgContext ctx) {
- CmdPushConstants(ctx->cmd, ctx->dev->pipelineLayout,
- VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(push_constants),&ctx->pushConsts);
- ctx->pushCstDirty = false;
-}
-void _update_cur_pattern (VkvgContext ctx, VkvgPattern pat) {
- VkvgPattern lastPat = ctx->pattern;
- ctx->pattern = pat;
-
- uint32_t newPatternType = VKVG_PATTERN_TYPE_SOLID;
-
- LOG(VKVG_LOG_INFO, "CTX: _update_cur_pattern: %p -> %p\n", lastPat, pat);
-
- if (pat == NULL) {//solid color
- if (lastPat == NULL)//solid
- return;//solid to solid transition, no extra action requested
- }else
- newPatternType = pat->type;
-
- switch (newPatternType) {
- case VKVG_PATTERN_TYPE_SOLID:
- _flush_cmd_buff (ctx);
- if (!_wait_ctx_flush_end (ctx))
- return;
- if (lastPat->type == VKVG_PATTERN_TYPE_SURFACE)//unbind current source surface by replacing it with empty texture
- _update_descriptor_set (ctx, ctx->dev->emptyImg, ctx->dsSrc);
- break;
- case VKVG_PATTERN_TYPE_SURFACE:
- {
- _emit_draw_cmd_undrawn_vertices(ctx);
-
- VkvgSurface surf = (VkvgSurface)pat->data;
-
- //flush ctx in two steps to add the src transitioning in the cmd buff
- if (ctx->cmdStarted){//transition of img without appropriate dependencies in subpass must be done outside renderpass.
- _end_render_pass (ctx);
- _flush_vertices_caches (ctx);
- } else {
- vkh_cmd_begin (ctx->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- ctx->cmdStarted = true;
- }
-
- //transition source surface for sampling
- vkh_image_set_layout (ctx->cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
-
- vkh_cmd_end (ctx->cmd);
- _wait_and_submit_cmd (ctx);
- if (!_wait_ctx_flush_end (ctx))
- return;
-
- VkSamplerAddressMode addrMode = 0;
- VkFilter filter = VK_FILTER_NEAREST;
- switch (pat->extend) {
- case VKVG_EXTEND_NONE:
- addrMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
- break;
- case VKVG_EXTEND_PAD:
- addrMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
- break;
- case VKVG_EXTEND_REPEAT:
- addrMode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
- break;
- case VKVG_EXTEND_REFLECT:
- addrMode = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
- break;
- }
- switch (pat->filter) {
- case VKVG_FILTER_BILINEAR:
- case VKVG_FILTER_BEST:
- filter = VK_FILTER_LINEAR;
- break;
- default:
- filter = VK_FILTER_NEAREST;
- break;
- }
- vkh_image_create_sampler (surf->img, filter, filter,
- VK_SAMPLER_MIPMAP_MODE_NEAREST, addrMode);
-
- _update_descriptor_set (ctx, surf->img, ctx->dsSrc);
-
- if (pat->hasMatrix) {
-
- }
-
- ctx->pushConsts.source.width = (float)surf->width;
- ctx->pushConsts.source.height = (float)surf->height;
- break;
- }
- case VKVG_PATTERN_TYPE_LINEAR:
- case VKVG_PATTERN_TYPE_RADIAL:
- _flush_cmd_buff (ctx);
- if (!_wait_ctx_flush_end (ctx))
- return;
-
- if (lastPat && lastPat->type == VKVG_PATTERN_TYPE_SURFACE)
- _update_descriptor_set (ctx, ctx->dev->emptyImg, ctx->dsSrc);
-
- vec4 bounds = {{(float)ctx->pSurf->width}, {(float)ctx->pSurf->height}, {0}, {0}};//store img bounds in unused source field
- ctx->pushConsts.source = bounds;
-
- //transform control point with current ctx matrix
- vkvg_gradient_t grad = *(vkvg_gradient_t*)pat->data;
-
- if (grad.count < 2) {
- ctx->status = VKVG_STATUS_PATTERN_INVALID_GRADIENT;
- return;
- }
- vkvg_matrix_t mat;
- if (pat->hasMatrix) {
- vkvg_pattern_get_matrix (pat, &mat);
- if (vkvg_matrix_invert (&mat) != VKVG_STATUS_SUCCESS)
- mat = VKVG_IDENTITY_MATRIX;
- }
-
- if (pat->hasMatrix)
- vkvg_matrix_transform_point (&mat, &grad.cp[0].x, &grad.cp[0].y);
- vkvg_matrix_transform_point (&ctx->pushConsts.mat, &grad.cp[0].x, &grad.cp[0].y);
- if (pat->type == VKVG_PATTERN_TYPE_LINEAR) {
- if (pat->hasMatrix)
- vkvg_matrix_transform_point (&mat, &grad.cp[0].z, &grad.cp[0].w);
- vkvg_matrix_transform_point (&ctx->pushConsts.mat, &grad.cp[0].z, &grad.cp[0].w);
- } else {
- if (pat->hasMatrix)
- vkvg_matrix_transform_point (&mat, &grad.cp[1].x, &grad.cp[1].y);
- vkvg_matrix_transform_point (&ctx->pushConsts.mat, &grad.cp[1].x, &grad.cp[1].y);
-
- //radii
- if (pat->hasMatrix) {
- vkvg_matrix_transform_distance (&mat, &grad.cp[0].z, &grad.cp[0].w);
- vkvg_matrix_transform_distance (&mat, &grad.cp[1].z, &grad.cp[0].w);
- }
- vkvg_matrix_transform_distance (&ctx->pushConsts.mat, &grad.cp[0].z, &grad.cp[0].w);
- vkvg_matrix_transform_distance (&ctx->pushConsts.mat, &grad.cp[1].z, &grad.cp[0].w);
- }
-
- memcpy (vkh_buffer_get_mapped_pointer(&ctx->uboGrad) , &grad, sizeof(vkvg_gradient_t));
- vkh_buffer_flush(&ctx->uboGrad);
- break;
- }
- ctx->pushConsts.fsq_patternType = (ctx->pushConsts.fsq_patternType & FULLSCREEN_BIT) + newPatternType;
- ctx->pushCstDirty = true;
- if (lastPat)
- vkvg_pattern_destroy (lastPat);
-}
-void _update_descriptor_set (VkvgContext ctx, VkhImage img, VkDescriptorSet ds){
- VkDescriptorImageInfo descSrcTex = vkh_image_get_descriptor (img, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
- VkWriteDescriptorSet writeDescriptorSet = {
- .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- .dstSet = ds,
- .dstBinding = 0,
- .descriptorCount = 1,
- .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- .pImageInfo = &descSrcTex
- };
- vkUpdateDescriptorSets(ctx->dev->vkDev, 1, &writeDescriptorSet, 0, NULL);
-}
-
-void _update_gradient_desc_set (VkvgContext ctx){
- VkDescriptorBufferInfo dbi = {ctx->uboGrad.buffer, 0, VK_WHOLE_SIZE};
- VkWriteDescriptorSet writeDescriptorSet = {
- .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- .dstSet = ctx->dsGrad,
- .dstBinding = 0,
- .descriptorCount = 1,
- .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
- .pBufferInfo = &dbi
- };
- vkUpdateDescriptorSets(ctx->dev->vkDev, 1, &writeDescriptorSet, 0, NULL);
+ CmdBeginRenderPass(ctx->cmd, &ctx->renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+ VkViewport viewport = {0, 0, (float)ctx->pSurf->width, (float)ctx->pSurf->height, 0, 1.f};
+ CmdSetViewport(ctx->cmd, 0, 1, &viewport);
+
+ CmdSetScissor(ctx->cmd, 0, 1, &ctx->bounds);
+
+ VkDescriptorSet dss[] = {ctx->dsFont, ctx->dsSrc, ctx->dsGrad};
+ CmdBindDescriptorSets(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelineLayout, 0, 3, dss, 0, NULL);
+
+ VkDeviceSize offsets[1] = {0};
+ CmdBindVertexBuffers(ctx->cmd, 0, 1, &ctx->vertices.buffer, offsets);
+ CmdBindIndexBuffer(ctx->cmd, ctx->indices.buffer, 0, VKVG_VK_INDEX_TYPE);
+
+ _update_push_constants(ctx);
+
+ _bind_draw_pipeline(ctx);
+ CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
+ ctx->cmdStarted = true;
+}
+// compute inverse mat used in shader when context matrix has changed
+// then trigger push constants command
+void _set_mat_inv_and_vkCmdPush(VkvgContext ctx) {
+ ctx->pushConsts.matInv = ctx->pushConsts.mat;
+ vkvg_matrix_invert(&ctx->pushConsts.matInv);
+ ctx->pushCstDirty = true;
+}
+void _update_push_constants(VkvgContext ctx) {
+ CmdPushConstants(ctx->cmd, ctx->dev->pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(push_constants),
+ &ctx->pushConsts);
+ ctx->pushCstDirty = false;
+}
+void _update_cur_pattern(VkvgContext ctx, VkvgPattern pat) {
+ VkvgPattern lastPat = ctx->pattern;
+ ctx->pattern = pat;
+
+ uint32_t newPatternType = VKVG_PATTERN_TYPE_SOLID;
+
+ LOG(VKVG_LOG_INFO, "CTX: _update_cur_pattern: %p -> %p\n", lastPat, pat);
+
+ if (pat == NULL) { // solid color
+ if (lastPat == NULL) // solid
+ return; // solid to solid transition, no extra action requested
+ } else
+ newPatternType = pat->type;
+
+ switch (newPatternType) {
+ case VKVG_PATTERN_TYPE_SOLID:
+ _flush_cmd_buff(ctx);
+ if (!_wait_ctx_flush_end(ctx))
+ return;
+ if (lastPat->type ==
+ VKVG_PATTERN_TYPE_SURFACE) // unbind current source surface by replacing it with empty texture
+ _update_descriptor_set(ctx, ctx->dev->emptyImg, ctx->dsSrc);
+ break;
+ case VKVG_PATTERN_TYPE_SURFACE: {
+ _emit_draw_cmd_undrawn_vertices(ctx);
+
+ VkvgSurface surf = (VkvgSurface)pat->data;
+
+ // flush ctx in two steps to add the src transitioning in the cmd buff
+ if (ctx->cmdStarted) { // transition of img without appropriate dependencies in subpass must be done outside
+ // renderpass.
+ _end_render_pass(ctx);
+ _flush_vertices_caches(ctx);
+ } else {
+ vkh_cmd_begin(ctx->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ ctx->cmdStarted = true;
+ }
+
+ // transition source surface for sampling
+ vkh_image_set_layout(ctx->cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+
+ vkh_cmd_end(ctx->cmd);
+ _wait_and_submit_cmd(ctx);
+ if (!_wait_ctx_flush_end(ctx))
+ return;
+
+ VkSamplerAddressMode addrMode = 0;
+ VkFilter filter = VK_FILTER_NEAREST;
+ switch (pat->extend) {
+ case VKVG_EXTEND_NONE:
+ addrMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
+ break;
+ case VKVG_EXTEND_PAD:
+ addrMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ break;
+ case VKVG_EXTEND_REPEAT:
+ addrMode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ break;
+ case VKVG_EXTEND_REFLECT:
+ addrMode = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
+ break;
+ }
+ switch (pat->filter) {
+ case VKVG_FILTER_BILINEAR:
+ case VKVG_FILTER_BEST:
+ filter = VK_FILTER_LINEAR;
+ break;
+ default:
+ filter = VK_FILTER_NEAREST;
+ break;
+ }
+ vkh_image_create_sampler(surf->img, filter, filter, VK_SAMPLER_MIPMAP_MODE_NEAREST, addrMode);
+
+ _update_descriptor_set(ctx, surf->img, ctx->dsSrc);
+
+ if (pat->hasMatrix) {
+ }
+
+ ctx->pushConsts.source.width = (float)surf->width;
+ ctx->pushConsts.source.height = (float)surf->height;
+ break;
+ }
+ case VKVG_PATTERN_TYPE_LINEAR:
+ case VKVG_PATTERN_TYPE_RADIAL:
+ _flush_cmd_buff(ctx);
+ if (!_wait_ctx_flush_end(ctx))
+ return;
+
+ if (lastPat && lastPat->type == VKVG_PATTERN_TYPE_SURFACE)
+ _update_descriptor_set(ctx, ctx->dev->emptyImg, ctx->dsSrc);
+
+ vec4 bounds = {{(float)ctx->pSurf->width},
+ {(float)ctx->pSurf->height},
+ {0},
+ {0}}; // store img bounds in unused source field
+ ctx->pushConsts.source = bounds;
+
+ // transform control point with current ctx matrix
+ vkvg_gradient_t grad = *(vkvg_gradient_t *)pat->data;
+
+ if (grad.count < 2) {
+ ctx->status = VKVG_STATUS_PATTERN_INVALID_GRADIENT;
+ return;
+ }
+ vkvg_matrix_t mat;
+ if (pat->hasMatrix) {
+ vkvg_pattern_get_matrix(pat, &mat);
+ if (vkvg_matrix_invert(&mat) != VKVG_STATUS_SUCCESS)
+ mat = VKVG_IDENTITY_MATRIX;
+ }
+
+ if (pat->hasMatrix)
+ vkvg_matrix_transform_point(&mat, &grad.cp[0].x, &grad.cp[0].y);
+ vkvg_matrix_transform_point(&ctx->pushConsts.mat, &grad.cp[0].x, &grad.cp[0].y);
+ if (pat->type == VKVG_PATTERN_TYPE_LINEAR) {
+ if (pat->hasMatrix)
+ vkvg_matrix_transform_point(&mat, &grad.cp[0].z, &grad.cp[0].w);
+ vkvg_matrix_transform_point(&ctx->pushConsts.mat, &grad.cp[0].z, &grad.cp[0].w);
+ } else {
+ if (pat->hasMatrix)
+ vkvg_matrix_transform_point(&mat, &grad.cp[1].x, &grad.cp[1].y);
+ vkvg_matrix_transform_point(&ctx->pushConsts.mat, &grad.cp[1].x, &grad.cp[1].y);
+
+ // radii
+ if (pat->hasMatrix) {
+ vkvg_matrix_transform_distance(&mat, &grad.cp[0].z, &grad.cp[0].w);
+ vkvg_matrix_transform_distance(&mat, &grad.cp[1].z, &grad.cp[0].w);
+ }
+ vkvg_matrix_transform_distance(&ctx->pushConsts.mat, &grad.cp[0].z, &grad.cp[0].w);
+ vkvg_matrix_transform_distance(&ctx->pushConsts.mat, &grad.cp[1].z, &grad.cp[0].w);
+ }
+
+ memcpy(vkh_buffer_get_mapped_pointer(&ctx->uboGrad), &grad, sizeof(vkvg_gradient_t));
+ vkh_buffer_flush(&ctx->uboGrad);
+ break;
+ }
+ ctx->pushConsts.fsq_patternType = (ctx->pushConsts.fsq_patternType & FULLSCREEN_BIT) + newPatternType;
+ ctx->pushCstDirty = true;
+ if (lastPat)
+ vkvg_pattern_destroy(lastPat);
+}
+void _update_descriptor_set(VkvgContext ctx, VkhImage img, VkDescriptorSet ds) {
+ VkDescriptorImageInfo descSrcTex = vkh_image_get_descriptor(img, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ VkWriteDescriptorSet writeDescriptorSet = {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = ds,
+ .dstBinding = 0,
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ .pImageInfo = &descSrcTex};
+ vkUpdateDescriptorSets(ctx->dev->vkDev, 1, &writeDescriptorSet, 0, NULL);
+}
+
+void _update_gradient_desc_set(VkvgContext ctx) {
+ VkDescriptorBufferInfo dbi = {ctx->uboGrad.buffer, 0, VK_WHOLE_SIZE};
+ VkWriteDescriptorSet writeDescriptorSet = {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = ctx->dsGrad,
+ .dstBinding = 0,
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ .pBufferInfo = &dbi};
+ vkUpdateDescriptorSets(ctx->dev->vkDev, 1, &writeDescriptorSet, 0, NULL);
}
/*
* Reset currently bound descriptor which image could be destroyed
*/
/*void _reset_src_descriptor_set (VkvgContext ctx){
- VkvgDevice dev = ctx->pSurf->dev;
- //VkDescriptorSet dss[] = {ctx->dsSrc};
- vkFreeDescriptorSets (dev->vkDev, ctx->descriptorPool, 1, &ctx->dsSrc);
-
- VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
- .descriptorPool = ctx->descriptorPool,
- .descriptorSetCount = 1,
- .pSetLayouts = &dev->dslSrc };
- VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsSrc));
+ VkvgDevice dev = ctx->pSurf->dev;
+ //VkDescriptorSet dss[] = {ctx->dsSrc};
+ vkFreeDescriptorSets (dev->vkDev, ctx->descriptorPool, 1, &ctx->dsSrc);
+
+ VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ .descriptorPool = ctx->descriptorPool,
+ .descriptorSetCount = 1,
+ .pSetLayouts = &dev->dslSrc };
+ VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsSrc));
}*/
-void _createDescriptorPool (VkvgContext ctx) {
- VkvgDevice dev = ctx->dev;
- const VkDescriptorPoolSize descriptorPoolSize[] = {
- {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 },
- {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 }
- };
- VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
- .maxSets = 3,
- .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
- .poolSizeCount = 2,
- .pPoolSizes = descriptorPoolSize };
- VK_CHECK_RESULT(vkCreateDescriptorPool (dev->vkDev, &descriptorPoolCreateInfo, NULL, &ctx->descriptorPool));
-}
-void _init_descriptor_sets (VkvgContext ctx){
- VkvgDevice dev = ctx->dev;
- VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
- .descriptorPool = ctx->descriptorPool,
- .descriptorSetCount = 1,
- .pSetLayouts = &dev->dslFont
- };
- VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsFont));
- descriptorSetAllocateInfo.pSetLayouts = &dev->dslSrc;
- VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsSrc));
- descriptorSetAllocateInfo.pSetLayouts = &dev->dslGrad;
- VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsGrad));
-}
-void _release_context_ressources (VkvgContext ctx) {
- VkDevice dev = ctx->dev->vkDev;
-
+void _createDescriptorPool(VkvgContext ctx) {
+ VkvgDevice dev = ctx->dev;
+ const VkDescriptorPoolSize descriptorPoolSize[] = {{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2},
+ {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1}};
+ VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ .maxSets = 3,
+ .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
+ .poolSizeCount = 2,
+ .pPoolSizes = descriptorPoolSize};
+ VK_CHECK_RESULT(vkCreateDescriptorPool(dev->vkDev, &descriptorPoolCreateInfo, NULL, &ctx->descriptorPool));
+}
+void _init_descriptor_sets(VkvgContext ctx) {
+ VkvgDevice dev = ctx->dev;
+ VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ .descriptorPool = ctx->descriptorPool,
+ .descriptorSetCount = 1,
+ .pSetLayouts = &dev->dslFont};
+ VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsFont));
+ descriptorSetAllocateInfo.pSetLayouts = &dev->dslSrc;
+ VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsSrc));
+ descriptorSetAllocateInfo.pSetLayouts = &dev->dslGrad;
+ VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsGrad));
+}
+void _release_context_ressources(VkvgContext ctx) {
+ VkDevice dev = ctx->dev->vkDev;
+
#ifndef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- vkDestroyFence (dev, ctx->flushFence, NULL);
+ vkDestroyFence(dev, ctx->flushFence, NULL);
#endif
- vkFreeCommandBuffers(dev, ctx->cmdPool, 2, ctx->cmdBuffers);
- vkDestroyCommandPool(dev, ctx->cmdPool, NULL);
-
- VkDescriptorSet dss[] = {ctx->dsFont, ctx->dsSrc, ctx->dsGrad};
- vkFreeDescriptorSets (dev, ctx->descriptorPool, 3, dss);
-
- vkDestroyDescriptorPool (dev, ctx->descriptorPool,NULL);
-
- vkh_buffer_reset (&ctx->uboGrad);
- vkh_buffer_reset (&ctx->indices);
- vkh_buffer_reset (&ctx->vertices);
-
- free(ctx->vertexCache);
- free(ctx->indexCache);
-
- vkh_image_destroy (ctx->fontCacheImg);
- //TODO:check this for source counter
- //vkh_image_destroy (ctx->source);
-
- free(ctx->pathes);
- free(ctx->points);
-
- free(ctx);
-}
-//populate vertice buff for stroke
-bool _build_vb_step(VkvgContext ctx, stroke_context_t* str, bool isCurve){
- Vertex v = {{0},ctx->curColor, {0,0,-1}};
- vec2 p0 = ctx->points[str->cp];
- vec2 v0 = vec2_sub(p0, ctx->points[str->iL]);
- vec2 v1 = vec2_sub(ctx->points[str->iR], p0);
- float length_v0 = vec2_length(v0);
- float length_v1 = vec2_length(v1);
- if (length_v0 < FLT_EPSILON || length_v1 < FLT_EPSILON) {
- LOG(VKVG_LOG_STROKE, "vb_step discard, length<epsilon: l0:%f l1:%f\n", length_v0, length_v1);
- return false;
- }
- vec2 v0n = vec2_div_s (v0, length_v0);
- vec2 v1n = vec2_div_s (v1, length_v1);
- float dot = vec2_dot (v0n, v1n);
- float det = v0n.x * v1n.y - v0n.y * v1n.x;
- if (EQUF(dot,1.0f)) {//colinear
- LOG(VKVG_LOG_STROKE, "vb_step discard, dot==1\n");
- return false;
- }
-
- if (EQUF(dot,-1.0f)) {//cusp (could draw line butt?)
- vec2 vPerp = vec2_mult_s(vec2_perp (v0n), str->hw);
-
- VKVG_IBO_INDEX_TYPE idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
-
- v.pos = vec2_add(p0, vPerp);
- _add_vertex(ctx, v);
- v.pos = vec2_sub(p0, vPerp);
- _add_vertex(ctx, v);
-
- _add_triangle_indices(ctx, idx, idx+1, idx+2);
- _add_triangle_indices(ctx, idx, idx+2, idx+3);
- LOG(VKVG_LOG_STROKE, "vb_step cusp, dot==-1\n");
- return true;
- }
-
- vec2 bisec_n = vec2_norm(vec2_add(v0n,v1n));//bisec/bisec_perp are inverted names
- float alpha = acosf(dot);
-
- if (det<0)
- alpha = -alpha;
-
- float halfAlpha = alpha / 2.f;
- float cosHalfAlpha = cosf(halfAlpha);
- float lh = str->hw / cosHalfAlpha;
- vec2 bisec_n_perp = vec2_perp(bisec_n);
-
- //limit bisectrice length
- float rlh = lh;//rlh is for inside pos tweeks
- if (dot < 0.f)
- rlh = fminf (rlh, fminf (length_v0, length_v1));
- //---
-
- vec2 bisec = vec2_mult_s (bisec_n_perp, rlh);
-
- VKVG_IBO_INDEX_TYPE idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
-
- vec2 rlh_inside_pos, rlh_outside_pos;
- if (rlh < lh) {
- vec2 vnPerp;
- if (length_v0 < length_v1)
- vnPerp = vec2_perp (v1n);
- else
- vnPerp = vec2_perp (v0n);
- vec2 vHwPerp = vec2_mult_s (vnPerp, str->hw);
-
- double lbc = cosHalfAlpha * rlh;
- if (det < 0.f) {
- rlh_inside_pos = vec2_add (vec2_add (vec2_mult_s(vnPerp, -lbc), vec2_add(p0, bisec)), vHwPerp);
- rlh_outside_pos = vec2_sub (p0, vec2_mult_s (bisec_n_perp, lh));
- } else {
- rlh_inside_pos = vec2_sub (vec2_add (vec2_mult_s(vnPerp, lbc), vec2_sub(p0, bisec)), vHwPerp);
- rlh_outside_pos = vec2_add (p0, vec2_mult_s (bisec_n_perp, lh));
- }
- } else {
- if (det < 0.0) {
- rlh_inside_pos = vec2_add (p0, bisec);
- rlh_outside_pos = vec2_sub (p0, bisec);
- } else {
- rlh_inside_pos = vec2_sub (p0, bisec);
- rlh_outside_pos = vec2_add (p0, bisec);
- }
- }
-
- vkvg_line_join_t join = ctx->lineJoin;
-
- if (isCurve) {
- if (dot < 0.8f)
- join = VKVG_LINE_JOIN_ROUND;
- else
- join = VKVG_LINE_JOIN_MITER;
- }
-
- if (join == VKVG_LINE_JOIN_MITER){
- if (lh > str->lhMax) {//miter limit
- double x = (lh - str->lhMax) * cosHalfAlpha;
- vec2 bisecPerp = vec2_mult_s (bisec_n, x);
- bisec = vec2_mult_s (bisec_n_perp, str->lhMax);
- if (det < 0) {
- v.pos = rlh_inside_pos;
- _add_vertex(ctx, v);
-
- vec2 p = vec2_sub(p0, bisec);
-
- v.pos = vec2_sub(p, bisecPerp);
- _add_vertex(ctx, v);
- v.pos = vec2_add(p, bisecPerp);
- _add_vertex(ctx, v);
-
- _add_triangle_indices(ctx, idx, idx+2, idx+1);
- _add_triangle_indices(ctx, idx+2, idx+4, idx);
- _add_triangle_indices(ctx, idx, idx+3, idx+4);
- return true;
- } else {
- vec2 p = vec2_add(p0, bisec);
- v.pos = vec2_sub(p, bisecPerp);
- _add_vertex(ctx, v);
-
- v.pos = rlh_inside_pos;
- _add_vertex(ctx, v);
-
- v.pos = vec2_add(p, bisecPerp);
- _add_vertex(ctx, v);
-
- _add_triangle_indices(ctx, idx, idx+2, idx+1);
- _add_triangle_indices(ctx, idx+2, idx+3, idx+1);
- _add_triangle_indices(ctx, idx+1, idx+3, idx+4);
- return false;
- }
-
- } else {//normal miter
- if (det < 0) {
- v.pos = rlh_inside_pos;
- _add_vertex(ctx, v);
- v.pos = rlh_outside_pos;
- _add_vertex(ctx, v);
- } else {
- v.pos = rlh_outside_pos;
- _add_vertex(ctx, v);
- v.pos = rlh_inside_pos;
- _add_vertex(ctx, v);
- }
-
- _add_tri_indices_for_rect(ctx, idx);
- return false;
- }
- }else{
- vec2 vp = vec2_perp(v0n);
-
- if (det<0){
- if (dot < 0 && rlh < lh)
- v.pos = rlh_inside_pos;
- else
- v.pos = vec2_add (p0, bisec);
- _add_vertex(ctx, v);
- v.pos = vec2_sub (p0, vec2_mult_s (vp, str->hw));
- }else{
- v.pos = vec2_add (p0, vec2_mult_s (vp, str->hw));
- _add_vertex(ctx, v);
- if (dot < 0 && rlh < lh)
- v.pos = rlh_inside_pos;
- else
- v.pos = vec2_sub (p0, bisec);
- }
- _add_vertex(ctx, v);
-
- if (join == VKVG_LINE_JOIN_BEVEL){
- if (det<0){
- _add_triangle_indices(ctx, idx, idx+2, idx+1);
- _add_triangle_indices(ctx, idx+2, idx+4, idx+0);
- _add_triangle_indices(ctx, idx, idx+3, idx+4);
- }else{
- _add_triangle_indices(ctx, idx, idx+2, idx+1);
- _add_triangle_indices(ctx, idx+2, idx+3, idx+1);
- _add_triangle_indices(ctx, idx+1, idx+3, idx+4);
- }
- }else if (join == VKVG_LINE_JOIN_ROUND){
- if (!str->arcStep)
- str->arcStep = _get_arc_step (ctx, str->hw);
- float a = acosf(vp.x);
- if (vp.y < 0)
- a = -a;
-
- if (det<0){
- a+=M_PIF;
- float a1 = a + alpha;
- a-=str->arcStep;
- while (a > a1){
- _add_vertexf(ctx, cosf(a) * str->hw + p0.x, sinf(a) * str->hw + p0.y);
- a-=str->arcStep;
- }
- }else{
- float a1 = a + alpha;
- a+=str->arcStep;
- while (a < a1){
- _add_vertexf(ctx, cosf(a) * str->hw + p0.x, sinf(a) * str->hw + p0.y);
- a+=str->arcStep;
- }
- }
- VKVG_IBO_INDEX_TYPE p0Idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
- _add_triangle_indices(ctx, idx, idx+2, idx+1);
- if (det < 0){
- for (VKVG_IBO_INDEX_TYPE p = idx+2; p < p0Idx; p++)
- _add_triangle_indices(ctx, p, p+1, idx);
- _add_triangle_indices(ctx, p0Idx, p0Idx+2, idx);
- _add_triangle_indices(ctx, idx, p0Idx+1, p0Idx+2);
- }else{
- for (VKVG_IBO_INDEX_TYPE p = idx+2; p < p0Idx; p++)
- _add_triangle_indices(ctx, p, p+1, idx+1);
- _add_triangle_indices(ctx, p0Idx, p0Idx+1, idx+1);
- _add_triangle_indices(ctx, idx+1, p0Idx+1, p0Idx+2);
- }
-
- }
-
- vp = vec2_mult_s (vec2_perp(v1n), str->hw);
- if (det < 0)
- v.pos = vec2_sub (p0, vp);
- else
- v.pos = vec2_add (p0, vp);
- _add_vertex(ctx, v);
- }
-
-/*
-#ifdef DEBUG
-
- debugLinePoints[dlpCount] = p0;
- debugLinePoints[dlpCount+1] = _v2add(p0, _vec2dToVec2(_v2Multd(v0n,10)));
- dlpCount+=2;
- debugLinePoints[dlpCount] = p0;
- debugLinePoints[dlpCount+1] = _v2add(p0, _vec2dToVec2(_v2Multd(v1n,10)));
- dlpCount+=2;
- debugLinePoints[dlpCount] = p0;
- debugLinePoints[dlpCount+1] = pR;
- dlpCount+=2;
-#endif*/
- /*if (reducedLH)
- return -det;
- else*/
- return (det < 0);
-}
-
-void _draw_stoke_cap (VkvgContext ctx, stroke_context_t *str, vec2 p0, vec2 n, bool isStart) {
- Vertex v = {{0},ctx->curColor,{0,0,-1}};
-
- VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
-
- if (isStart){
- vec2 vhw = vec2_mult_s (n, str->hw);
-
- if (ctx->lineCap == VKVG_LINE_CAP_SQUARE)
- p0 = vec2_sub (p0, vhw);
-
- vhw = vec2_perp (vhw);
-
- if (ctx->lineCap == VKVG_LINE_CAP_ROUND){
- if (!str->arcStep)
- str->arcStep = _get_arc_step (ctx, str->hw);
-
- float a = acosf(n.x) + M_PIF_2;
- if (n.y < 0)
- a = M_PIF-a;
- float a1 = a + M_PIF;
-
- a += str->arcStep;
- while (a < a1){
- _add_vertexf (ctx, cosf(a) * str->hw + p0.x, sinf(a) * str->hw + p0.y);
- a += str->arcStep;
- }
- VKVG_IBO_INDEX_TYPE p0Idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
- for (VKVG_IBO_INDEX_TYPE p = firstIdx; p < p0Idx; p++)
- _add_triangle_indices (ctx, p0Idx+1, p, p+1);
- firstIdx = p0Idx;
- }
-
- v.pos = vec2_add (p0, vhw);
- _add_vertex (ctx, v);
- v.pos = vec2_sub (p0, vhw);
- _add_vertex (ctx, v);
-
- _add_tri_indices_for_rect (ctx, firstIdx);
- }else{
- vec2 vhw = vec2_mult_s (n, str->hw);
-
- if (ctx->lineCap == VKVG_LINE_CAP_SQUARE)
- p0 = vec2_add (p0, vhw);
-
- vhw = vec2_perp (vhw);
-
- v.pos = vec2_add (p0, vhw);
- _add_vertex (ctx, v);
- v.pos = vec2_sub (p0, vhw);
- _add_vertex (ctx, v);
-
- firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
-
- if (ctx->lineCap == VKVG_LINE_CAP_ROUND){
- if (!str->arcStep)
- str->arcStep = _get_arc_step (ctx, str->hw);
-
- float a = acosf(n.x)+ M_PIF_2;
- if (n.y < 0)
- a = M_PIF-a;
- float a1 = a - M_PIF;
-
- a -= str->arcStep;
- while ( a > a1){
- _add_vertexf (ctx, cosf(a) * str->hw + p0.x, sinf(a) * str->hw + p0.y);
- a -= str->arcStep;
- }
-
- VKVG_IBO_INDEX_TYPE p0Idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset - 1);
- for (VKVG_IBO_INDEX_TYPE p = firstIdx-1 ; p < p0Idx; p++)
- _add_triangle_indices (ctx, p+1, p, firstIdx-2);
- }
- }
-}
-float _draw_dashed_segment (VkvgContext ctx, stroke_context_t* str, dash_context_t* dc, bool isCurve) {
- //vec2 pL = ctx->points[str->iL];
- vec2 p = ctx->points[str->cp];
- vec2 pR = ctx->points[str->iR];
-
- if (!dc->dashOn)//we test in fact the next dash start, if dashOn = true => next segment is a void.
- _build_vb_step (ctx, str, isCurve);
-
- vec2 d = vec2_sub (pR, p);
- dc->normal = vec2_norm (d);
- float segmentLength = vec2_length(d);
-
- while (dc->curDashOffset < segmentLength){
- vec2 p0 = vec2_add (p, vec2_mult_s(dc->normal, dc->curDashOffset));
-
- _draw_stoke_cap (ctx, str, p0, dc->normal, dc->dashOn);
- dc->dashOn ^= true;
- dc->curDashOffset += ctx->dashes[dc->curDash];
- if (++dc->curDash == ctx->dashCount)
- dc->curDash = 0;
- }
- dc->curDashOffset -= segmentLength;
- dc->curDashOffset = fmodf(dc->curDashOffset, dc->totDashLength);
- return segmentLength;
-}
-void _draw_segment (VkvgContext ctx, stroke_context_t* str, dash_context_t* dc, bool isCurve) {
- str->iR = str->cp + 1;
- if (ctx->dashCount > 0)
- _draw_dashed_segment(ctx, str, dc, isCurve);
- else
- _build_vb_step (ctx, str, isCurve);
- str->iL = str->cp++;
- if (ctx->vertCount - ctx->curVertOffset > VKVG_IBO_MAX / 3) {
- Vertex v0 = ctx->vertexCache[ctx->curVertOffset + str->firstIdx];
- Vertex v1 = ctx->vertexCache[ctx->curVertOffset + str->firstIdx + 1];
- _emit_draw_cmd_undrawn_vertices(ctx);
- //repeat first 2 vertices for closed pathes
- str->firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
- _add_vertex(ctx, v0);
- _add_vertex(ctx, v1);
- ctx->curVertOffset = ctx->vertCount;//prevent redrawing them at the start of the batch
- }
+ vkFreeCommandBuffers(dev, ctx->cmdPool, 2, ctx->cmdBuffers);
+ vkDestroyCommandPool(dev, ctx->cmdPool, NULL);
+
+ VkDescriptorSet dss[] = {ctx->dsFont, ctx->dsSrc, ctx->dsGrad};
+ vkFreeDescriptorSets(dev, ctx->descriptorPool, 3, dss);
+
+ vkDestroyDescriptorPool(dev, ctx->descriptorPool, NULL);
+
+ vkh_buffer_reset(&ctx->uboGrad);
+ vkh_buffer_reset(&ctx->indices);
+ vkh_buffer_reset(&ctx->vertices);
+
+ free(ctx->vertexCache);
+ free(ctx->indexCache);
+
+ vkh_image_destroy(ctx->fontCacheImg);
+ // TODO:check this for source counter
+ // vkh_image_destroy (ctx->source);
+
+ free(ctx->pathes);
+ free(ctx->points);
+
+ free(ctx);
+}
+// populate vertice buff for stroke
+bool _build_vb_step(VkvgContext ctx, stroke_context_t *str, bool isCurve) {
+ Vertex v = {{0}, ctx->curColor, {0, 0, -1}};
+ vec2 p0 = ctx->points[str->cp];
+ vec2 v0 = vec2_sub(p0, ctx->points[str->iL]);
+ vec2 v1 = vec2_sub(ctx->points[str->iR], p0);
+ float length_v0 = vec2_length(v0);
+ float length_v1 = vec2_length(v1);
+ if (length_v0 < FLT_EPSILON || length_v1 < FLT_EPSILON) {
+ LOG(VKVG_LOG_STROKE, "vb_step discard, length<epsilon: l0:%f l1:%f\n", length_v0, length_v1);
+ return false;
+ }
+ vec2 v0n = vec2_div_s(v0, length_v0);
+ vec2 v1n = vec2_div_s(v1, length_v1);
+ float dot = vec2_dot(v0n, v1n);
+ float det = v0n.x * v1n.y - v0n.y * v1n.x;
+ if (EQUF(dot, 1.0f)) { // colinear
+ LOG(VKVG_LOG_STROKE, "vb_step discard, dot==1\n");
+ return false;
+ }
+
+ if (EQUF(dot, -1.0f)) { // cusp (could draw line butt?)
+ vec2 vPerp = vec2_mult_s(vec2_perp(v0n), str->hw);
+
+ VKVG_IBO_INDEX_TYPE idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+
+ v.pos = vec2_add(p0, vPerp);
+ _add_vertex(ctx, v);
+ v.pos = vec2_sub(p0, vPerp);
+ _add_vertex(ctx, v);
+
+ _add_triangle_indices(ctx, idx, idx + 1, idx + 2);
+ _add_triangle_indices(ctx, idx, idx + 2, idx + 3);
+ LOG(VKVG_LOG_STROKE, "vb_step cusp, dot==-1\n");
+ return true;
+ }
+
+ vec2 bisec_n = vec2_norm(vec2_add(v0n, v1n)); // bisec/bisec_perp are inverted names
+ float alpha = acosf(dot);
+
+ if (det < 0)
+ alpha = -alpha;
+
+ float halfAlpha = alpha / 2.f;
+ float cosHalfAlpha = cosf(halfAlpha);
+ float lh = str->hw / cosHalfAlpha;
+ vec2 bisec_n_perp = vec2_perp(bisec_n);
+
+ // limit bisectrice length
+ float rlh = lh; // rlh is for inside pos tweeks
+ if (dot < 0.f)
+ rlh = fminf(rlh, fminf(length_v0, length_v1));
+ //---
+
+ vec2 bisec = vec2_mult_s(bisec_n_perp, rlh);
+
+ VKVG_IBO_INDEX_TYPE idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+
+ vec2 rlh_inside_pos, rlh_outside_pos;
+ if (rlh < lh) {
+ vec2 vnPerp;
+ if (length_v0 < length_v1)
+ vnPerp = vec2_perp(v1n);
+ else
+ vnPerp = vec2_perp(v0n);
+ vec2 vHwPerp = vec2_mult_s(vnPerp, str->hw);
+
+ double lbc = cosHalfAlpha * rlh;
+ if (det < 0.f) {
+ rlh_inside_pos = vec2_add(vec2_add(vec2_mult_s(vnPerp, -lbc), vec2_add(p0, bisec)), vHwPerp);
+ rlh_outside_pos = vec2_sub(p0, vec2_mult_s(bisec_n_perp, lh));
+ } else {
+ rlh_inside_pos = vec2_sub(vec2_add(vec2_mult_s(vnPerp, lbc), vec2_sub(p0, bisec)), vHwPerp);
+ rlh_outside_pos = vec2_add(p0, vec2_mult_s(bisec_n_perp, lh));
+ }
+ } else {
+ if (det < 0.0) {
+ rlh_inside_pos = vec2_add(p0, bisec);
+ rlh_outside_pos = vec2_sub(p0, bisec);
+ } else {
+ rlh_inside_pos = vec2_sub(p0, bisec);
+ rlh_outside_pos = vec2_add(p0, bisec);
+ }
+ }
+
+ vkvg_line_join_t join = ctx->lineJoin;
+
+ if (isCurve) {
+ if (dot < 0.8f)
+ join = VKVG_LINE_JOIN_ROUND;
+ else
+ join = VKVG_LINE_JOIN_MITER;
+ }
+
+ if (join == VKVG_LINE_JOIN_MITER) {
+ if (lh > str->lhMax) { // miter limit
+ double x = (lh - str->lhMax) * cosHalfAlpha;
+ vec2 bisecPerp = vec2_mult_s(bisec_n, x);
+ bisec = vec2_mult_s(bisec_n_perp, str->lhMax);
+ if (det < 0) {
+ v.pos = rlh_inside_pos;
+ _add_vertex(ctx, v);
+
+ vec2 p = vec2_sub(p0, bisec);
+
+ v.pos = vec2_sub(p, bisecPerp);
+ _add_vertex(ctx, v);
+ v.pos = vec2_add(p, bisecPerp);
+ _add_vertex(ctx, v);
+
+ _add_triangle_indices(ctx, idx, idx + 2, idx + 1);
+ _add_triangle_indices(ctx, idx + 2, idx + 4, idx);
+ _add_triangle_indices(ctx, idx, idx + 3, idx + 4);
+ return true;
+ } else {
+ vec2 p = vec2_add(p0, bisec);
+ v.pos = vec2_sub(p, bisecPerp);
+ _add_vertex(ctx, v);
+
+ v.pos = rlh_inside_pos;
+ _add_vertex(ctx, v);
+
+ v.pos = vec2_add(p, bisecPerp);
+ _add_vertex(ctx, v);
+
+ _add_triangle_indices(ctx, idx, idx + 2, idx + 1);
+ _add_triangle_indices(ctx, idx + 2, idx + 3, idx + 1);
+ _add_triangle_indices(ctx, idx + 1, idx + 3, idx + 4);
+ return false;
+ }
+
+ } else { // normal miter
+ if (det < 0) {
+ v.pos = rlh_inside_pos;
+ _add_vertex(ctx, v);
+ v.pos = rlh_outside_pos;
+ _add_vertex(ctx, v);
+ } else {
+ v.pos = rlh_outside_pos;
+ _add_vertex(ctx, v);
+ v.pos = rlh_inside_pos;
+ _add_vertex(ctx, v);
+ }
+
+ _add_tri_indices_for_rect(ctx, idx);
+ return false;
+ }
+ } else {
+ vec2 vp = vec2_perp(v0n);
+
+ if (det < 0) {
+ if (dot < 0 && rlh < lh)
+ v.pos = rlh_inside_pos;
+ else
+ v.pos = vec2_add(p0, bisec);
+ _add_vertex(ctx, v);
+ v.pos = vec2_sub(p0, vec2_mult_s(vp, str->hw));
+ } else {
+ v.pos = vec2_add(p0, vec2_mult_s(vp, str->hw));
+ _add_vertex(ctx, v);
+ if (dot < 0 && rlh < lh)
+ v.pos = rlh_inside_pos;
+ else
+ v.pos = vec2_sub(p0, bisec);
+ }
+ _add_vertex(ctx, v);
+
+ if (join == VKVG_LINE_JOIN_BEVEL) {
+ if (det < 0) {
+ _add_triangle_indices(ctx, idx, idx + 2, idx + 1);
+ _add_triangle_indices(ctx, idx + 2, idx + 4, idx + 0);
+ _add_triangle_indices(ctx, idx, idx + 3, idx + 4);
+ } else {
+ _add_triangle_indices(ctx, idx, idx + 2, idx + 1);
+ _add_triangle_indices(ctx, idx + 2, idx + 3, idx + 1);
+ _add_triangle_indices(ctx, idx + 1, idx + 3, idx + 4);
+ }
+ } else if (join == VKVG_LINE_JOIN_ROUND) {
+ if (!str->arcStep)
+ str->arcStep = _get_arc_step(ctx, str->hw);
+ float a = acosf(vp.x);
+ if (vp.y < 0)
+ a = -a;
+
+ if (det < 0) {
+ a += M_PIF;
+ float a1 = a + alpha;
+ a -= str->arcStep;
+ while (a > a1) {
+ _add_vertexf(ctx, cosf(a) * str->hw + p0.x, sinf(a) * str->hw + p0.y);
+ a -= str->arcStep;
+ }
+ } else {
+ float a1 = a + alpha;
+ a += str->arcStep;
+ while (a < a1) {
+ _add_vertexf(ctx, cosf(a) * str->hw + p0.x, sinf(a) * str->hw + p0.y);
+ a += str->arcStep;
+ }
+ }
+ VKVG_IBO_INDEX_TYPE p0Idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+ _add_triangle_indices(ctx, idx, idx + 2, idx + 1);
+ if (det < 0) {
+ for (VKVG_IBO_INDEX_TYPE p = idx + 2; p < p0Idx; p++)
+ _add_triangle_indices(ctx, p, p + 1, idx);
+ _add_triangle_indices(ctx, p0Idx, p0Idx + 2, idx);
+ _add_triangle_indices(ctx, idx, p0Idx + 1, p0Idx + 2);
+ } else {
+ for (VKVG_IBO_INDEX_TYPE p = idx + 2; p < p0Idx; p++)
+ _add_triangle_indices(ctx, p, p + 1, idx + 1);
+ _add_triangle_indices(ctx, p0Idx, p0Idx + 1, idx + 1);
+ _add_triangle_indices(ctx, idx + 1, p0Idx + 1, p0Idx + 2);
+ }
+ }
+
+ vp = vec2_mult_s(vec2_perp(v1n), str->hw);
+ if (det < 0)
+ v.pos = vec2_sub(p0, vp);
+ else
+ v.pos = vec2_add(p0, vp);
+ _add_vertex(ctx, v);
+ }
+
+ /*
+ #ifdef DEBUG
+
+ debugLinePoints[dlpCount] = p0;
+ debugLinePoints[dlpCount+1] = _v2add(p0, _vec2dToVec2(_v2Multd(v0n,10)));
+ dlpCount+=2;
+ debugLinePoints[dlpCount] = p0;
+ debugLinePoints[dlpCount+1] = _v2add(p0, _vec2dToVec2(_v2Multd(v1n,10)));
+ dlpCount+=2;
+ debugLinePoints[dlpCount] = p0;
+ debugLinePoints[dlpCount+1] = pR;
+ dlpCount+=2;
+ #endif*/
+ /*if (reducedLH)
+ return -det;
+ else*/
+ return (det < 0);
+}
+
+void _draw_stoke_cap(VkvgContext ctx, stroke_context_t *str, vec2 p0, vec2 n, bool isStart) {
+ Vertex v = {{0}, ctx->curColor, {0, 0, -1}};
+
+ VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+
+ if (isStart) {
+ vec2 vhw = vec2_mult_s(n, str->hw);
+
+ if (ctx->lineCap == VKVG_LINE_CAP_SQUARE)
+ p0 = vec2_sub(p0, vhw);
+
+ vhw = vec2_perp(vhw);
+
+ if (ctx->lineCap == VKVG_LINE_CAP_ROUND) {
+ if (!str->arcStep)
+ str->arcStep = _get_arc_step(ctx, str->hw);
+
+ float a = acosf(n.x) + M_PIF_2;
+ if (n.y < 0)
+ a = M_PIF - a;
+ float a1 = a + M_PIF;
+
+ a += str->arcStep;
+ while (a < a1) {
+ _add_vertexf(ctx, cosf(a) * str->hw + p0.x, sinf(a) * str->hw + p0.y);
+ a += str->arcStep;
+ }
+ VKVG_IBO_INDEX_TYPE p0Idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+ for (VKVG_IBO_INDEX_TYPE p = firstIdx; p < p0Idx; p++)
+ _add_triangle_indices(ctx, p0Idx + 1, p, p + 1);
+ firstIdx = p0Idx;
+ }
+
+ v.pos = vec2_add(p0, vhw);
+ _add_vertex(ctx, v);
+ v.pos = vec2_sub(p0, vhw);
+ _add_vertex(ctx, v);
+
+ _add_tri_indices_for_rect(ctx, firstIdx);
+ } else {
+ vec2 vhw = vec2_mult_s(n, str->hw);
+
+ if (ctx->lineCap == VKVG_LINE_CAP_SQUARE)
+ p0 = vec2_add(p0, vhw);
+
+ vhw = vec2_perp(vhw);
+
+ v.pos = vec2_add(p0, vhw);
+ _add_vertex(ctx, v);
+ v.pos = vec2_sub(p0, vhw);
+ _add_vertex(ctx, v);
+
+ firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+
+ if (ctx->lineCap == VKVG_LINE_CAP_ROUND) {
+ if (!str->arcStep)
+ str->arcStep = _get_arc_step(ctx, str->hw);
+
+ float a = acosf(n.x) + M_PIF_2;
+ if (n.y < 0)
+ a = M_PIF - a;
+ float a1 = a - M_PIF;
+
+ a -= str->arcStep;
+ while (a > a1) {
+ _add_vertexf(ctx, cosf(a) * str->hw + p0.x, sinf(a) * str->hw + p0.y);
+ a -= str->arcStep;
+ }
+
+ VKVG_IBO_INDEX_TYPE p0Idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset - 1);
+ for (VKVG_IBO_INDEX_TYPE p = firstIdx - 1; p < p0Idx; p++)
+ _add_triangle_indices(ctx, p + 1, p, firstIdx - 2);
+ }
+ }
+}
+float _draw_dashed_segment(VkvgContext ctx, stroke_context_t *str, dash_context_t *dc, bool isCurve) {
+ // vec2 pL = ctx->points[str->iL];
+ vec2 p = ctx->points[str->cp];
+ vec2 pR = ctx->points[str->iR];
+
+ if (!dc->dashOn) // we test in fact the next dash start, if dashOn = true => next segment is a void.
+ _build_vb_step(ctx, str, isCurve);
+
+ vec2 d = vec2_sub(pR, p);
+ dc->normal = vec2_norm(d);
+ float segmentLength = vec2_length(d);
+
+ while (dc->curDashOffset < segmentLength) {
+ vec2 p0 = vec2_add(p, vec2_mult_s(dc->normal, dc->curDashOffset));
+
+ _draw_stoke_cap(ctx, str, p0, dc->normal, dc->dashOn);
+ dc->dashOn ^= true;
+ dc->curDashOffset += ctx->dashes[dc->curDash];
+ if (++dc->curDash == ctx->dashCount)
+ dc->curDash = 0;
+ }
+ dc->curDashOffset -= segmentLength;
+ dc->curDashOffset = fmodf(dc->curDashOffset, dc->totDashLength);
+ return segmentLength;
+}
+void _draw_segment(VkvgContext ctx, stroke_context_t *str, dash_context_t *dc, bool isCurve) {
+ str->iR = str->cp + 1;
+ if (ctx->dashCount > 0)
+ _draw_dashed_segment(ctx, str, dc, isCurve);
+ else
+ _build_vb_step(ctx, str, isCurve);
+ str->iL = str->cp++;
+ if (ctx->vertCount - ctx->curVertOffset > VKVG_IBO_MAX / 3) {
+ Vertex v0 = ctx->vertexCache[ctx->curVertOffset + str->firstIdx];
+ Vertex v1 = ctx->vertexCache[ctx->curVertOffset + str->firstIdx + 1];
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ // repeat first 2 vertices for closed pathes
+ str->firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+ _add_vertex(ctx, v0);
+ _add_vertex(ctx, v1);
+ ctx->curVertOffset = ctx->vertCount; // prevent redrawing them at the start of the batch
+ }
}
bool ptInTriangle(vec2 p, vec2 p0, vec2 p1, vec2 p2) {
- float dX = p.x-p2.x;
- float dY = p.y-p2.y;
- float dX21 = p2.x-p1.x;
- float dY12 = p1.y-p2.y;
- float D = dY12*(p0.x-p2.x) + dX21*(p0.y-p2.y);
- float s = dY12*dX + dX21*dY;
- float t = (p2.y-p0.y)*dX + (p0.x-p2.x)*dY;
- if (D<0)
- return (s<=0) && (t<=0) && (s+t>=D);
- return (s>=0) && (t>=0) && (s+t<=D);
-}
-
-void _free_ctx_save (vkvg_context_save_t* sav){
- if (sav->dashCount > 0)
- free (sav->dashes);
- if (sav->pattern)
- vkvg_pattern_destroy(sav->pattern);
- free (sav);
-}
-
-
-#define M_APPROXIMATION_SCALE 1.0
-#define M_ANGLE_TOLERANCE 0.01
-#define M_CUSP_LIMIT 0.01
-#define CURVE_RECURSION_LIMIT 100
-#define CURVE_COLLINEARITY_EPSILON 1.7
+ float dX = p.x - p2.x;
+ float dY = p.y - p2.y;
+ float dX21 = p2.x - p1.x;
+ float dY12 = p1.y - p2.y;
+ float D = dY12 * (p0.x - p2.x) + dX21 * (p0.y - p2.y);
+ float s = dY12 * dX + dX21 * dY;
+ float t = (p2.y - p0.y) * dX + (p0.x - p2.x) * dY;
+ if (D < 0)
+ return (s <= 0) && (t <= 0) && (s + t >= D);
+ return (s >= 0) && (t >= 0) && (s + t <= D);
+}
+
+void _free_ctx_save(vkvg_context_save_t *sav) {
+ if (sav->dashCount > 0)
+ free(sav->dashes);
+ if (sav->pattern)
+ vkvg_pattern_destroy(sav->pattern);
+ free(sav);
+}
+
+#define M_APPROXIMATION_SCALE 1.0
+#define M_ANGLE_TOLERANCE 0.01
+#define M_CUSP_LIMIT 0.01
+#define CURVE_RECURSION_LIMIT 100
+#define CURVE_COLLINEARITY_EPSILON 1.7
#define CURVE_ANGLE_TOLERANCE_EPSILON 0.001
-//no floating point arithmetic operation allowed in macro.
-#pragma warning(disable:4127)
-void _recursive_bezier (VkvgContext ctx, float distanceTolerance,
- float x1, float y1, float x2, float y2,
- float x3, float y3, float x4, float y4,
- unsigned level) {
- if(level > CURVE_RECURSION_LIMIT)
- {
- return;
- }
-
- // Calculate all the mid-points of the line segments
- //----------------------
- float x12 = (x1 + x2) / 2;
- float y12 = (y1 + y2) / 2;
- float x23 = (x2 + x3) / 2;
- float y23 = (y2 + y3) / 2;
- float x34 = (x3 + x4) / 2;
- float y34 = (y3 + y4) / 2;
- float x123 = (x12 + x23) / 2;
- float y123 = (y12 + y23) / 2;
- float x234 = (x23 + x34) / 2;
- float y234 = (y23 + y34) / 2;
- float x1234 = (x123 + x234) / 2;
- float y1234 = (y123 + y234) / 2;
-
- if(level > 0) // Enforce subdivision first time
- {
- // Try to approximate the full cubic curve by a single straight line
- //------------------
- float dx = x4-x1;
- float dy = y4-y1;
-
- float d2 = fabsf(((x2 - x4) * dy - (y2 - y4) * dx));
- float d3 = fabsf(((x3 - x4) * dy - (y3 - y4) * dx));
-
- float da1, da2;
-
- if(d2 > CURVE_COLLINEARITY_EPSILON && d3 > CURVE_COLLINEARITY_EPSILON)
- {
- // Regular care
- //-----------------
- if((d2 + d3)*(d2 + d3) <= (dx*dx + dy*dy) * distanceTolerance)
- {
- // If the curvature doesn't exceed the distance_tolerance value
- // we tend to finish subdivisions.
- //----------------------
- if (M_ANGLE_TOLERANCE < CURVE_ANGLE_TOLERANCE_EPSILON) {
- _add_point(ctx, x1234, y1234);
- return;
- }
-
- // Angle & Cusp Condition
- //----------------------
- float a23 = atan2f(y3 - y2, x3 - x2);
- da1 = fabsf(a23 - atan2f(y2 - y1, x2 - x1));
- da2 = fabsf(atan2f(y4 - y3, x4 - x3) - a23);
- if(da1 >= M_PIF) da1 = M_2_PIF - da1;
- if(da2 >= M_PIF) da2 = M_2_PIF - da2;
-
- if(da1 + da2 < (float)M_ANGLE_TOLERANCE)
- {
- // Finally we can stop the recursion
- //----------------------
- _add_point (ctx, x1234, y1234);
- return;
- }
-
- if(M_CUSP_LIMIT != 0.0)
- {
- if(da1 > M_CUSP_LIMIT)
- {
- _add_point (ctx, x2, y2);
- return;
- }
-
- if(da2 > M_CUSP_LIMIT)
- {
- _add_point (ctx, x3, y3);
- return;
- }
- }
- }
- } else {
- if(d2 > CURVE_COLLINEARITY_EPSILON)
- {
- // p1,p3,p4 are collinear, p2 is considerable
- //----------------------
- if(d2 * d2 <= distanceTolerance * (dx*dx + dy*dy))
- {
- if(M_ANGLE_TOLERANCE < CURVE_ANGLE_TOLERANCE_EPSILON)
- {
- _add_point (ctx, x1234, y1234);
- return;
- }
-
- // Angle Condition
- //----------------------
- da1 = fabsf(atan2f(y3 - y2, x3 - x2) - atan2f(y2 - y1, x2 - x1));
- if(da1 >= M_PIF) da1 = M_2_PIF - da1;
-
- if(da1 < M_ANGLE_TOLERANCE)
- {
- _add_point (ctx, x2, y2);
- _add_point (ctx, x3, y3);
- return;
- }
-
- if(M_CUSP_LIMIT != 0.0)
- {
- if(da1 > M_CUSP_LIMIT)
- {
- _add_point (ctx, x2, y2);
- return;
- }
- }
- }
- } else if(d3 > CURVE_COLLINEARITY_EPSILON) {
- // p1,p2,p4 are collinear, p3 is considerable
- //----------------------
- if(d3 * d3 <= distanceTolerance* (dx*dx + dy*dy))
- {
- if(M_ANGLE_TOLERANCE < CURVE_ANGLE_TOLERANCE_EPSILON)
- {
- _add_point (ctx, x1234, y1234);
- return;
- }
-
- // Angle Condition
- //----------------------
- da1 = fabsf(atan2f(y4 - y3, x4 - x3) - atan2f(y3 - y2, x3 - x2));
- if(da1 >= M_PIF) da1 = M_2_PIF - da1;
-
- if(da1 < M_ANGLE_TOLERANCE)
- {
- _add_point (ctx, x2, y2);
- _add_point (ctx, x3, y3);
- return;
- }
-
- if(M_CUSP_LIMIT != 0.0)
- {
- if(da1 > M_CUSP_LIMIT)
- {
- _add_point (ctx, x3, y3);
- return;
- }
- }
- }
- }
- else
- {
- // Collinear case
- //-----------------
- dx = x1234 - (x1 + x4) / 2;
- dy = y1234 - (y1 + y4) / 2;
- if(dx*dx + dy*dy <= distanceTolerance)
- {
- _add_point (ctx, x1234, y1234);
- return;
- }
- }
- }
- }
-
- // Continue subdivision
- //----------------------
- _recursive_bezier (ctx, distanceTolerance, x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1);
- _recursive_bezier (ctx, distanceTolerance,x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1);
-}
-#pragma warning(default:4127)
-void _line_to (VkvgContext ctx, float x, float y) {
- vec2 p = {x,y};
- if (!_current_path_is_empty (ctx)){
- //prevent adding the same point
- if (vec2_equ (_get_current_position (ctx), p))
- return;
- }
- _add_point (ctx, x, y);
- ctx->simpleConvex = false;
-}
-void _elliptic_arc (VkvgContext ctx, float x1, float y1, float x2, float y2, bool largeArc, bool counterClockWise, float _rx, float _ry, float phi) {
- if (ctx->status)
- return;
-
- if (_rx==0||_ry==0) {
- if (_current_path_is_empty(ctx))
- vkvg_move_to(ctx, x1, y1);
- vkvg_line_to(ctx, x2, y2);
- return;
- }
- float rx = fabsf(_rx);
- float ry = fabsf(_ry);
-
- mat2 m = {
- { cosf (phi), sinf (phi)},
- {-sinf (phi), cosf (phi)}
- };
- vec2 p = {(x1 - x2)/2, (y1 - y2)/2};
- vec2 p1 = mat2_mult_vec2 (m, p);
-
- //radii corrections
- double lambda = powf (p1.x, 2) / powf (rx, 2) + powf (p1.y, 2) / powf (ry, 2);
- if (lambda > 1) {
- lambda = sqrtf (lambda);
- rx *= lambda;
- ry *= lambda;
- }
-
- p = (vec2){rx * p1.y / ry, -ry * p1.x / rx};
-
- vec2 cp = vec2_mult_s (p, sqrtf (fabsf (
- (powf (rx,2) * powf (ry,2) - powf (rx,2) * powf (p1.y, 2) - powf (ry,2) * powf (p1.x, 2)) /
- (powf (rx,2) * powf (p1.y, 2) + powf (ry,2) * powf (p1.x, 2))
- )));
-
- if (largeArc == counterClockWise)
- vec2_inv(&cp);
-
- m = (mat2) {
- {cosf (phi),-sinf (phi)},
- {sinf (phi), cosf (phi)}
- };
- p = (vec2){(x1 + x2)/2, (y1 + y2)/2};
- vec2 c = vec2_add (mat2_mult_vec2(m, cp) , p);
-
- vec2 u = vec2_unit_x;
- vec2 v = {(p1.x-cp.x)/rx, (p1.y-cp.y)/ry};
- double sa = acosf (vec2_dot (u, v) / (fabsf(vec2_length(v)) * fabsf(vec2_length(u))));
- if (isnan(sa))
- sa=M_PIF;
- if (u.x*v.y-u.y*v.x < 0)
- sa = -sa;
-
- u = v;
- v = (vec2) {(-p1.x-cp.x)/rx, (-p1.y-cp.y)/ry};
- double delta_theta = acosf (vec2_dot (u, v) / (fabsf(vec2_length (v)) * fabsf(vec2_length (u))));
- if (isnan(delta_theta))
- delta_theta=M_PIF;
- if (u.x*v.y-u.y*v.x < 0)
- delta_theta = -delta_theta;
-
- if (counterClockWise) {
- if (delta_theta < 0)
- delta_theta += M_PIF * 2.0;
- } else if (delta_theta > 0)
- delta_theta -= M_PIF * 2.0;
-
- m = (mat2) {
- {cosf (phi),-sinf (phi)},
- {sinf (phi), cosf (phi)}
- };
-
- double theta = sa;
- double ea = sa + delta_theta;
-
- float step = fmaxf(0.001f, fminf(M_PIF, _get_arc_step(ctx, fminf (rx, ry))*0.1f));
-
- p = (vec2) {
- rx * cosf (theta),
- ry * sinf (theta)
- };
- vec2 xy = vec2_add (mat2_mult_vec2 (m, p), c);
-
- if (_current_path_is_empty(ctx)){
- _set_curve_start (ctx);
- _add_point (ctx, xy.x, xy.y);
- if (!ctx->pathPtr)
- ctx->simpleConvex = true;
- else
- ctx->simpleConvex = false;
- }else{
- _line_to(ctx, xy.x, xy.y);
- _set_curve_start (ctx);
- ctx->simpleConvex = false;
- }
-
- _set_curve_start (ctx);
-
- if (sa < ea) {
- theta += step;
- while (theta < ea) {
- p = (vec2) {
- rx * cosf (theta),
- ry * sinf (theta)
- };
- xy = vec2_add (mat2_mult_vec2 (m, p), c);
- _add_point (ctx, xy.x, xy.y);
- theta += step;
- }
- } else {
- theta -= step;
- while (theta > ea) {
- p = (vec2) {
- rx * cosf (theta),
- ry * sinf (theta)
- };
- xy = vec2_add (mat2_mult_vec2 (m, p), c);
- _add_point (ctx, xy.x, xy.y);
- theta -= step;
- }
- }
- p = (vec2) {
- rx * cosf (ea),
- ry * sinf (ea)
- };
- xy = vec2_add (mat2_mult_vec2 (m, p), c);
- _add_point (ctx, xy.x, xy.y);
- _set_curve_end(ctx);
-}
-
-
-//Even-Odd inside test with stencil buffer implementation.
-void _poly_fill (VkvgContext ctx, vec4* bounds){
- //we anticipate the check for vbo buffer size, ibo is not used in poly_fill
- //the polyfill emit a single vertex for each point in the path.
- if (ctx->sizeVBO - VKVG_ARRAY_THRESHOLD < ctx->vertCount + ctx->pointCount) {
- if (ctx->cmdStarted) {
- _end_render_pass (ctx);
- if (ctx->vertCount > 0)
- _flush_vertices_caches (ctx);
- vkh_cmd_end (ctx->cmd);
- _wait_and_submit_cmd (ctx);
- _wait_ctx_flush_end (ctx);
- if (ctx->sizeVBO - VKVG_ARRAY_THRESHOLD < ctx->pointCount){
- _resize_vbo (ctx, ctx->pointCount + VKVG_ARRAY_THRESHOLD);
- _resize_vertex_cache (ctx, ctx->sizeVBO);
- }
- }else{
- _resize_vbo (ctx, ctx->vertCount + ctx->pointCount + VKVG_ARRAY_THRESHOLD);
- _resize_vertex_cache (ctx, ctx->sizeVBO);
- }
-
- _start_cmd_for_render_pass(ctx);
- } else {
- _ensure_vertex_cache_size (ctx, ctx->pointCount);
- _ensure_renderpass_is_started (ctx);
- }
-
- CmdBindPipeline (ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelinePolyFill);
-
- Vertex v = {{0}, ctx->curColor, {0,0,-1}};
- uint32_t ptrPath = 0;
- uint32_t firstPtIdx = 0;
-
- while (ptrPath < ctx->pathPtr){
- uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
- if (pathPointCount > 2) {
- VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)ctx->vertCount;
-
- for (uint32_t i = 0; i < pathPointCount; i++) {
- v.pos = ctx->points [i+firstPtIdx];
- ctx->vertexCache[ctx->vertCount++] = v;
- if (!bounds)
- continue;
- //bounds are computed here to scissor the painting operation
- //that speed up fill drastically.
- vkvg_matrix_transform_point (&ctx->pushConsts.mat, &v.pos.x, &v.pos.y);
-
- if (v.pos.x < bounds->xMin)
- bounds->xMin = v.pos.x;
- if (v.pos.x > bounds->xMax)
- bounds->xMax = v.pos.x;
- if (v.pos.y < bounds->yMin)
- bounds->yMin = v.pos.y;
- if (v.pos.y > bounds->yMax)
- bounds->yMax = v.pos.y;
- }
-
- LOG(VKVG_LOG_INFO_PATH, "\tpoly fill: point count = %d; 1st vert = %d; vert count = %d\n", pathPointCount, firstVertIdx, ctx->vertCount - firstVertIdx);
- CmdDraw (ctx->cmd, pathPointCount, 1, firstVertIdx , 0);
- }
- firstPtIdx += pathPointCount;
-
- if (_path_has_curves (ctx, ptrPath)) {
- //skip segments lengths used in stroke
- ptrPath++;
- uint32_t totPts = 0;
- while (totPts < pathPointCount)
- totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
- }else
- ptrPath++;
- }
- ctx->curVertOffset = ctx->vertCount;
+// no floating point arithmetic operation allowed in macro.
+#pragma warning(disable : 4127)
+void _recursive_bezier(VkvgContext ctx, float distanceTolerance, float x1, float y1, float x2, float y2, float x3,
+ float y3, float x4, float y4, unsigned level) {
+ if (level > CURVE_RECURSION_LIMIT) {
+ return;
+ }
+
+ // Calculate all the mid-points of the line segments
+ //----------------------
+ float x12 = (x1 + x2) / 2;
+ float y12 = (y1 + y2) / 2;
+ float x23 = (x2 + x3) / 2;
+ float y23 = (y2 + y3) / 2;
+ float x34 = (x3 + x4) / 2;
+ float y34 = (y3 + y4) / 2;
+ float x123 = (x12 + x23) / 2;
+ float y123 = (y12 + y23) / 2;
+ float x234 = (x23 + x34) / 2;
+ float y234 = (y23 + y34) / 2;
+ float x1234 = (x123 + x234) / 2;
+ float y1234 = (y123 + y234) / 2;
+
+ if (level > 0) // Enforce subdivision first time
+ {
+ // Try to approximate the full cubic curve by a single straight line
+ //------------------
+ float dx = x4 - x1;
+ float dy = y4 - y1;
+
+ float d2 = fabsf(((x2 - x4) * dy - (y2 - y4) * dx));
+ float d3 = fabsf(((x3 - x4) * dy - (y3 - y4) * dx));
+
+ float da1, da2;
+
+ if (d2 > CURVE_COLLINEARITY_EPSILON && d3 > CURVE_COLLINEARITY_EPSILON) {
+ // Regular care
+ //-----------------
+ if ((d2 + d3) * (d2 + d3) <= (dx * dx + dy * dy) * distanceTolerance) {
+ // If the curvature doesn't exceed the distance_tolerance value
+ // we tend to finish subdivisions.
+ //----------------------
+ if (M_ANGLE_TOLERANCE < CURVE_ANGLE_TOLERANCE_EPSILON) {
+ _add_point(ctx, x1234, y1234);
+ return;
+ }
+
+ // Angle & Cusp Condition
+ //----------------------
+ float a23 = atan2f(y3 - y2, x3 - x2);
+ da1 = fabsf(a23 - atan2f(y2 - y1, x2 - x1));
+ da2 = fabsf(atan2f(y4 - y3, x4 - x3) - a23);
+ if (da1 >= M_PIF)
+ da1 = M_2_PIF - da1;
+ if (da2 >= M_PIF)
+ da2 = M_2_PIF - da2;
+
+ if (da1 + da2 < (float)M_ANGLE_TOLERANCE) {
+ // Finally we can stop the recursion
+ //----------------------
+ _add_point(ctx, x1234, y1234);
+ return;
+ }
+
+ if (M_CUSP_LIMIT != 0.0) {
+ if (da1 > M_CUSP_LIMIT) {
+ _add_point(ctx, x2, y2);
+ return;
+ }
+
+ if (da2 > M_CUSP_LIMIT) {
+ _add_point(ctx, x3, y3);
+ return;
+ }
+ }
+ }
+ } else {
+ if (d2 > CURVE_COLLINEARITY_EPSILON) {
+ // p1,p3,p4 are collinear, p2 is considerable
+ //----------------------
+ if (d2 * d2 <= distanceTolerance * (dx * dx + dy * dy)) {
+ if (M_ANGLE_TOLERANCE < CURVE_ANGLE_TOLERANCE_EPSILON) {
+ _add_point(ctx, x1234, y1234);
+ return;
+ }
+
+ // Angle Condition
+ //----------------------
+ da1 = fabsf(atan2f(y3 - y2, x3 - x2) - atan2f(y2 - y1, x2 - x1));
+ if (da1 >= M_PIF)
+ da1 = M_2_PIF - da1;
+
+ if (da1 < M_ANGLE_TOLERANCE) {
+ _add_point(ctx, x2, y2);
+ _add_point(ctx, x3, y3);
+ return;
+ }
+
+ if (M_CUSP_LIMIT != 0.0) {
+ if (da1 > M_CUSP_LIMIT) {
+ _add_point(ctx, x2, y2);
+ return;
+ }
+ }
+ }
+ } else if (d3 > CURVE_COLLINEARITY_EPSILON) {
+ // p1,p2,p4 are collinear, p3 is considerable
+ //----------------------
+ if (d3 * d3 <= distanceTolerance * (dx * dx + dy * dy)) {
+ if (M_ANGLE_TOLERANCE < CURVE_ANGLE_TOLERANCE_EPSILON) {
+ _add_point(ctx, x1234, y1234);
+ return;
+ }
+
+ // Angle Condition
+ //----------------------
+ da1 = fabsf(atan2f(y4 - y3, x4 - x3) - atan2f(y3 - y2, x3 - x2));
+ if (da1 >= M_PIF)
+ da1 = M_2_PIF - da1;
+
+ if (da1 < M_ANGLE_TOLERANCE) {
+ _add_point(ctx, x2, y2);
+ _add_point(ctx, x3, y3);
+ return;
+ }
+
+ if (M_CUSP_LIMIT != 0.0) {
+ if (da1 > M_CUSP_LIMIT) {
+ _add_point(ctx, x3, y3);
+ return;
+ }
+ }
+ }
+ } else {
+ // Collinear case
+ //-----------------
+ dx = x1234 - (x1 + x4) / 2;
+ dy = y1234 - (y1 + y4) / 2;
+ if (dx * dx + dy * dy <= distanceTolerance) {
+ _add_point(ctx, x1234, y1234);
+ return;
+ }
+ }
+ }
+ }
+
+ // Continue subdivision
+ //----------------------
+ _recursive_bezier(ctx, distanceTolerance, x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1);
+ _recursive_bezier(ctx, distanceTolerance, x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1);
+}
+#pragma warning(default : 4127)
+void _line_to(VkvgContext ctx, float x, float y) {
+ vec2 p = {x, y};
+ if (!_current_path_is_empty(ctx)) {
+ // prevent adding the same point
+ if (vec2_equ(_get_current_position(ctx), p))
+ return;
+ }
+ _add_point(ctx, x, y);
+ ctx->simpleConvex = false;
+}
+void _elliptic_arc(VkvgContext ctx, float x1, float y1, float x2, float y2, bool largeArc, bool counterClockWise,
+ float _rx, float _ry, float phi) {
+ if (ctx->status)
+ return;
+
+ if (_rx == 0 || _ry == 0) {
+ if (_current_path_is_empty(ctx))
+ vkvg_move_to(ctx, x1, y1);
+ vkvg_line_to(ctx, x2, y2);
+ return;
+ }
+ float rx = fabsf(_rx);
+ float ry = fabsf(_ry);
+
+ mat2 m = {{cosf(phi), sinf(phi)}, {-sinf(phi), cosf(phi)}};
+ vec2 p = {(x1 - x2) / 2, (y1 - y2) / 2};
+ vec2 p1 = mat2_mult_vec2(m, p);
+
+ // radii corrections
+ double lambda = powf(p1.x, 2) / powf(rx, 2) + powf(p1.y, 2) / powf(ry, 2);
+ if (lambda > 1) {
+ lambda = sqrtf(lambda);
+ rx *= lambda;
+ ry *= lambda;
+ }
+
+ p = (vec2){rx * p1.y / ry, -ry * p1.x / rx};
+
+ vec2 cp = vec2_mult_s(
+ p, sqrtf(fabsf((powf(rx, 2) * powf(ry, 2) - powf(rx, 2) * powf(p1.y, 2) - powf(ry, 2) * powf(p1.x, 2)) /
+ (powf(rx, 2) * powf(p1.y, 2) + powf(ry, 2) * powf(p1.x, 2)))));
+
+ if (largeArc == counterClockWise)
+ vec2_inv(&cp);
+
+ m = (mat2){{cosf(phi), -sinf(phi)}, {sinf(phi), cosf(phi)}};
+ p = (vec2){(x1 + x2) / 2, (y1 + y2) / 2};
+ vec2 c = vec2_add(mat2_mult_vec2(m, cp), p);
+
+ vec2 u = vec2_unit_x;
+ vec2 v = {(p1.x - cp.x) / rx, (p1.y - cp.y) / ry};
+ double sa = acosf(vec2_dot(u, v) / (fabsf(vec2_length(v)) * fabsf(vec2_length(u))));
+ if (isnan(sa))
+ sa = M_PIF;
+ if (u.x * v.y - u.y * v.x < 0)
+ sa = -sa;
+
+ u = v;
+ v = (vec2){(-p1.x - cp.x) / rx, (-p1.y - cp.y) / ry};
+ double delta_theta = acosf(vec2_dot(u, v) / (fabsf(vec2_length(v)) * fabsf(vec2_length(u))));
+ if (isnan(delta_theta))
+ delta_theta = M_PIF;
+ if (u.x * v.y - u.y * v.x < 0)
+ delta_theta = -delta_theta;
+
+ if (counterClockWise) {
+ if (delta_theta < 0)
+ delta_theta += M_PIF * 2.0;
+ } else if (delta_theta > 0)
+ delta_theta -= M_PIF * 2.0;
+
+ m = (mat2){{cosf(phi), -sinf(phi)}, {sinf(phi), cosf(phi)}};
+
+ double theta = sa;
+ double ea = sa + delta_theta;
+
+ float step = fmaxf(0.001f, fminf(M_PIF, _get_arc_step(ctx, fminf(rx, ry)) * 0.1f));
+
+ p = (vec2){rx * cosf(theta), ry * sinf(theta)};
+ vec2 xy = vec2_add(mat2_mult_vec2(m, p), c);
+
+ if (_current_path_is_empty(ctx)) {
+ _set_curve_start(ctx);
+ _add_point(ctx, xy.x, xy.y);
+ if (!ctx->pathPtr)
+ ctx->simpleConvex = true;
+ else
+ ctx->simpleConvex = false;
+ } else {
+ _line_to(ctx, xy.x, xy.y);
+ _set_curve_start(ctx);
+ ctx->simpleConvex = false;
+ }
+
+ _set_curve_start(ctx);
+
+ if (sa < ea) {
+ theta += step;
+ while (theta < ea) {
+ p = (vec2){rx * cosf(theta), ry * sinf(theta)};
+ xy = vec2_add(mat2_mult_vec2(m, p), c);
+ _add_point(ctx, xy.x, xy.y);
+ theta += step;
+ }
+ } else {
+ theta -= step;
+ while (theta > ea) {
+ p = (vec2){rx * cosf(theta), ry * sinf(theta)};
+ xy = vec2_add(mat2_mult_vec2(m, p), c);
+ _add_point(ctx, xy.x, xy.y);
+ theta -= step;
+ }
+ }
+ p = (vec2){rx * cosf(ea), ry * sinf(ea)};
+ xy = vec2_add(mat2_mult_vec2(m, p), c);
+ _add_point(ctx, xy.x, xy.y);
+ _set_curve_end(ctx);
+}
+
+// Even-Odd inside test with stencil buffer implementation.
+void _poly_fill(VkvgContext ctx, vec4 *bounds) {
+ // we anticipate the check for vbo buffer size, ibo is not used in poly_fill
+ // the polyfill emit a single vertex for each point in the path.
+ if (ctx->sizeVBO - VKVG_ARRAY_THRESHOLD < ctx->vertCount + ctx->pointCount) {
+ if (ctx->cmdStarted) {
+ _end_render_pass(ctx);
+ if (ctx->vertCount > 0)
+ _flush_vertices_caches(ctx);
+ vkh_cmd_end(ctx->cmd);
+ _wait_and_submit_cmd(ctx);
+ _wait_ctx_flush_end(ctx);
+ if (ctx->sizeVBO - VKVG_ARRAY_THRESHOLD < ctx->pointCount) {
+ _resize_vbo(ctx, ctx->pointCount + VKVG_ARRAY_THRESHOLD);
+ _resize_vertex_cache(ctx, ctx->sizeVBO);
+ }
+ } else {
+ _resize_vbo(ctx, ctx->vertCount + ctx->pointCount + VKVG_ARRAY_THRESHOLD);
+ _resize_vertex_cache(ctx, ctx->sizeVBO);
+ }
+
+ _start_cmd_for_render_pass(ctx);
+ } else {
+ _ensure_vertex_cache_size(ctx, ctx->pointCount);
+ _ensure_renderpass_is_started(ctx);
+ }
+
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->dev->pipelinePolyFill);
+
+ Vertex v = {{0}, ctx->curColor, {0, 0, -1}};
+ uint32_t ptrPath = 0;
+ uint32_t firstPtIdx = 0;
+
+ while (ptrPath < ctx->pathPtr) {
+ uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+ if (pathPointCount > 2) {
+ VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)ctx->vertCount;
+
+ for (uint32_t i = 0; i < pathPointCount; i++) {
+ v.pos = ctx->points[i + firstPtIdx];
+ ctx->vertexCache[ctx->vertCount++] = v;
+ if (!bounds)
+ continue;
+ // bounds are computed here to scissor the painting operation
+ // that speed up fill drastically.
+ vkvg_matrix_transform_point(&ctx->pushConsts.mat, &v.pos.x, &v.pos.y);
+
+ if (v.pos.x < bounds->xMin)
+ bounds->xMin = v.pos.x;
+ if (v.pos.x > bounds->xMax)
+ bounds->xMax = v.pos.x;
+ if (v.pos.y < bounds->yMin)
+ bounds->yMin = v.pos.y;
+ if (v.pos.y > bounds->yMax)
+ bounds->yMax = v.pos.y;
+ }
+
+ LOG(VKVG_LOG_INFO_PATH, "\tpoly fill: point count = %d; 1st vert = %d; vert count = %d\n", pathPointCount,
+ firstVertIdx, ctx->vertCount - firstVertIdx);
+ CmdDraw(ctx->cmd, pathPointCount, 1, firstVertIdx, 0);
+ }
+ firstPtIdx += pathPointCount;
+
+ if (_path_has_curves(ctx, ptrPath)) {
+ // skip segments lengths used in stroke
+ ptrPath++;
+ uint32_t totPts = 0;
+ while (totPts < pathPointCount)
+ totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
+ } else
+ ptrPath++;
+ }
+ ctx->curVertOffset = ctx->vertCount;
}
#ifdef VKVG_FILL_NZ_GLUTESS
void fan_vertex2(VKVG_IBO_INDEX_TYPE v, VkvgContext ctx) {
- VKVG_IBO_INDEX_TYPE i = (VKVG_IBO_INDEX_TYPE)v;
- switch (ctx->tesselator_idx_counter) {
- case 0:
- _add_indice(ctx, i);
- ctx->tesselator_fan_start = i;
- ctx->tesselator_idx_counter ++;
- break;
- case 1:
- case 2:
- _add_indice(ctx, i);
- ctx->tesselator_idx_counter ++;
- break;
- default:
- _add_indice_for_fan (ctx, i);
- break;
- }
+ VKVG_IBO_INDEX_TYPE i = (VKVG_IBO_INDEX_TYPE)v;
+ switch (ctx->tesselator_idx_counter) {
+ case 0:
+ _add_indice(ctx, i);
+ ctx->tesselator_fan_start = i;
+ ctx->tesselator_idx_counter++;
+ break;
+ case 1:
+ case 2:
+ _add_indice(ctx, i);
+ ctx->tesselator_idx_counter++;
+ break;
+ default:
+ _add_indice_for_fan(ctx, i);
+ break;
+ }
}
void strip_vertex2(VKVG_IBO_INDEX_TYPE v, VkvgContext ctx) {
- VKVG_IBO_INDEX_TYPE i = (VKVG_IBO_INDEX_TYPE)v;
- if (ctx->tesselator_idx_counter < 3) {
- _add_indice(ctx, i);
- } else
- _add_indice_for_strip(ctx, i, ctx->tesselator_idx_counter % 2);
- ctx->tesselator_idx_counter ++;
-}
-
-void triangle_vertex2 (VKVG_IBO_INDEX_TYPE v, VkvgContext ctx) {
- VKVG_IBO_INDEX_TYPE i = (VKVG_IBO_INDEX_TYPE)v;
- _add_indice(ctx, i);
-}
-void skip_vertex2 (VKVG_IBO_INDEX_TYPE v, VkvgContext ctx) {}
-void begin2(GLenum which, void *poly_data)
-{
- VkvgContext ctx = (VkvgContext)poly_data;
- switch (which) {
- case GL_TRIANGLES:
- ctx->vertex_cb = &triangle_vertex2;
- break;
- case GL_TRIANGLE_STRIP:
- ctx->tesselator_idx_counter = 0;
- ctx->vertex_cb = &strip_vertex2;
- break;
- case GL_TRIANGLE_FAN:
- ctx->tesselator_idx_counter = ctx->tesselator_fan_start = 0;
- ctx->vertex_cb = &fan_vertex2;
- break;
- default:
- fprintf(stderr, "ERROR, can't handle %d\n", (int)which);
- ctx->vertex_cb = &skip_vertex2;
- }
-}
-
-void combine2(const GLdouble newVertex[3],
- const void *neighborVertex_s[4],
- const GLfloat neighborWeight[4], void **outData, void *poly_data)
-{
- VkvgContext ctx = (VkvgContext)poly_data;
- Vertex v = {{newVertex[0],newVertex[1]},ctx->curColor, {0,0,-1}};
- *outData = (void*)((unsigned long)(ctx->vertCount - ctx->curVertOffset));
- _add_vertex(ctx, v);
-}
-void vertex2(void *vertex_data, void *poly_data)
-{
- VKVG_IBO_INDEX_TYPE i = (VKVG_IBO_INDEX_TYPE)vertex_data;
- VkvgContext ctx = (VkvgContext)poly_data;
- ctx->vertex_cb(i, ctx);
-}
-void _fill_non_zero (VkvgContext ctx){
- Vertex v = {{0},ctx->curColor, {0,0,-1}};
-
- uint32_t ptrPath = 0;
- uint32_t firstPtIdx = 0;
-
- if (ctx->pathPtr == 1 && ctx->pathes[0] & PATH_IS_CONVEX_BIT) {
- //simple concave rectangle or circle
- VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
- uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
-
- _ensure_vertex_cache_size(ctx, pathPointCount);
- _ensure_index_cache_size(ctx, (pathPointCount-2)*3);
-
- VKVG_IBO_INDEX_TYPE i = 0;
- while (i < 2){
- v.pos = ctx->points [i++];
- _set_vertex (ctx, ctx->vertCount++, v);
- }
- while (i < pathPointCount){
- v.pos = ctx->points [i];
- _set_vertex (ctx, ctx->vertCount++, v);
- _add_triangle_indices_unchecked(ctx, firstVertIdx, firstVertIdx + i - 1, firstVertIdx + i);
- i++;
- }
- return;
- }
-
-
- GLUtesselator *tess = gluNewTess();
- gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
- gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (*) ()) &vertex2);
- gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (*) ()) &begin2);
- gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (GLvoid (*) ()) &combine2);
-
- gluTessBeginPolygon(tess, ctx);
-
- while (ptrPath < ctx->pathPtr){
- uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
-
- if (pathPointCount > 2) {
- VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
- gluTessBeginContour(tess);
-
- VKVG_IBO_INDEX_TYPE i = 0;
-
- while (i < pathPointCount){
- v.pos = ctx->points[i+firstPtIdx];
- double dp[] = {v.pos.x,v.pos.y,0};
- _add_vertex(ctx, v);
- gluTessVertex(tess, dp, (void*)((unsigned long)firstVertIdx + i));
- i++;
- }
- gluTessEndContour(tess);
-
- //limit batch size here to 1/3 of the ibo index type ability
- //if (ctx->vertCount - ctx->curVertOffset > VKVG_IBO_MAX / 3)
- // _emit_draw_cmd_undrawn_vertices(ctx);
- }
-
- firstPtIdx += pathPointCount;
- if (_path_has_curves (ctx, ptrPath)) {
- //skip segments lengths used in stroke
- ptrPath++;
- uint32_t totPts = 0;
- while (totPts < pathPointCount)
- totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
- }else
- ptrPath++;
- }
-
- gluTessEndPolygon(tess);
-
- gluDeleteTess(tess);
+ VKVG_IBO_INDEX_TYPE i = (VKVG_IBO_INDEX_TYPE)v;
+ if (ctx->tesselator_idx_counter < 3) {
+ _add_indice(ctx, i);
+ } else
+ _add_indice_for_strip(ctx, i, ctx->tesselator_idx_counter % 2);
+ ctx->tesselator_idx_counter++;
+}
+
+void triangle_vertex2(VKVG_IBO_INDEX_TYPE v, VkvgContext ctx) {
+ VKVG_IBO_INDEX_TYPE i = (VKVG_IBO_INDEX_TYPE)v;
+ _add_indice(ctx, i);
+}
+void skip_vertex2(VKVG_IBO_INDEX_TYPE v, VkvgContext ctx) {}
+void begin2(GLenum which, void *poly_data) {
+ VkvgContext ctx = (VkvgContext)poly_data;
+ switch (which) {
+ case GL_TRIANGLES:
+ ctx->vertex_cb = &triangle_vertex2;
+ break;
+ case GL_TRIANGLE_STRIP:
+ ctx->tesselator_idx_counter = 0;
+ ctx->vertex_cb = &strip_vertex2;
+ break;
+ case GL_TRIANGLE_FAN:
+ ctx->tesselator_idx_counter = ctx->tesselator_fan_start = 0;
+ ctx->vertex_cb = &fan_vertex2;
+ break;
+ default:
+ fprintf(stderr, "ERROR, can't handle %d\n", (int)which);
+ ctx->vertex_cb = &skip_vertex2;
+ }
+}
+
+void combine2(const GLdouble newVertex[3], const void *neighborVertex_s[4], const GLfloat neighborWeight[4],
+ void **outData, void *poly_data) {
+ VkvgContext ctx = (VkvgContext)poly_data;
+ Vertex v = {{newVertex[0], newVertex[1]}, ctx->curColor, {0, 0, -1}};
+ *outData = (void *)((unsigned long)(ctx->vertCount - ctx->curVertOffset));
+ _add_vertex(ctx, v);
+}
+void vertex2(void *vertex_data, void *poly_data) {
+ VKVG_IBO_INDEX_TYPE i = (VKVG_IBO_INDEX_TYPE)vertex_data;
+ VkvgContext ctx = (VkvgContext)poly_data;
+ ctx->vertex_cb(i, ctx);
+}
+void _fill_non_zero(VkvgContext ctx) {
+ Vertex v = {{0}, ctx->curColor, {0, 0, -1}};
+
+ uint32_t ptrPath = 0;
+ uint32_t firstPtIdx = 0;
+
+ if (ctx->pathPtr == 1 && ctx->pathes[0] & PATH_IS_CONVEX_BIT) {
+ // simple concave rectangle or circle
+ VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+ uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+
+ _ensure_vertex_cache_size(ctx, pathPointCount);
+ _ensure_index_cache_size(ctx, (pathPointCount - 2) * 3);
+
+ VKVG_IBO_INDEX_TYPE i = 0;
+ while (i < 2) {
+ v.pos = ctx->points[i++];
+ _set_vertex(ctx, ctx->vertCount++, v);
+ }
+ while (i < pathPointCount) {
+ v.pos = ctx->points[i];
+ _set_vertex(ctx, ctx->vertCount++, v);
+ _add_triangle_indices_unchecked(ctx, firstVertIdx, firstVertIdx + i - 1, firstVertIdx + i);
+ i++;
+ }
+ return;
+ }
+
+ GLUtesselator *tess = gluNewTess();
+ gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
+ gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid(*)()) & vertex2);
+ gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid(*)()) & begin2);
+ gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (GLvoid(*)()) & combine2);
+
+ gluTessBeginPolygon(tess, ctx);
+
+ while (ptrPath < ctx->pathPtr) {
+ uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+
+ if (pathPointCount > 2) {
+ VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+ gluTessBeginContour(tess);
+
+ VKVG_IBO_INDEX_TYPE i = 0;
+
+ while (i < pathPointCount) {
+ v.pos = ctx->points[i + firstPtIdx];
+ double dp[] = {v.pos.x, v.pos.y, 0};
+ _add_vertex(ctx, v);
+ gluTessVertex(tess, dp, (void *)((unsigned long)firstVertIdx + i));
+ i++;
+ }
+ gluTessEndContour(tess);
+
+ // limit batch size here to 1/3 of the ibo index type ability
+ // if (ctx->vertCount - ctx->curVertOffset > VKVG_IBO_MAX / 3)
+ // _emit_draw_cmd_undrawn_vertices(ctx);
+ }
+
+ firstPtIdx += pathPointCount;
+ if (_path_has_curves(ctx, ptrPath)) {
+ // skip segments lengths used in stroke
+ ptrPath++;
+ uint32_t totPts = 0;
+ while (totPts < pathPointCount)
+ totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
+ } else
+ ptrPath++;
+ }
+
+ gluTessEndPolygon(tess);
+
+ gluDeleteTess(tess);
}
#else
-//create fill from current path with ear clipping technic
-void _fill_non_zero (VkvgContext ctx){
- Vertex v = {{0},ctx->curColor, {0,0,-1}};
-
- uint32_t ptrPath = 0;
- uint32_t firstPtIdx = 0;
-
- while (ptrPath < ctx->pathPtr){
- uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
-
- if (pathPointCount > 2) {
- VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
- //ear_clip_point* ecps = (ear_clip_point*)malloc(pathPointCount*sizeof(ear_clip_point));
- ear_clip_point ecps[pathPointCount];
- uint32_t ecps_count = pathPointCount;
- VKVG_IBO_INDEX_TYPE i = 0;
-
- //init points link list
- while (i < pathPointCount-1){
- v.pos = ctx->points[i+firstPtIdx];
- ear_clip_point ecp = {v.pos, firstVertIdx+i, &ecps[i+1]};
- ecps[i] = ecp;
- _add_vertex(ctx, v);
- i++;
- }
-
- v.pos = ctx->points[i+firstPtIdx];
- ear_clip_point ecp = {v.pos, firstVertIdx+i, ecps};
- ecps[i] = ecp;
- _add_vertex(ctx, v);
-
- ear_clip_point* ecp_current = ecps;
- uint32_t tries = 0;
-
- while (ecps_count > 3) {
- if (tries > ecps_count) {
- break;
- }
- ear_clip_point* v0 = ecp_current->next,
- *v1 = ecp_current, *v2 = ecp_current->next->next;
- if (ecp_zcross (v0, v2, v1)<0){
- ecp_current = ecp_current->next;
- tries++;
- continue;
- }
- ear_clip_point* vP = v2->next;
- bool isEar = true;
- while (vP!=v1){
- if (ptInTriangle (vP->pos, v0->pos, v2->pos, v1->pos)){
- isEar = false;
- break;
- }
- vP = vP->next;
- }
- if (isEar){
- _add_triangle_indices (ctx, v0->idx, v1->idx, v2->idx);
- v1->next = v2;
- ecps_count --;
- tries = 0;
- }else{
- ecp_current = ecp_current->next;
- tries++;
- }
- }
- if (ecps_count == 3)
- _add_triangle_indices(ctx, ecp_current->next->idx, ecp_current->idx, ecp_current->next->next->idx);
-
- //limit batch size here to 1/3 of the ibo index type ability
- if (ctx->vertCount - ctx->curVertOffset > VKVG_IBO_MAX / 3)
- _emit_draw_cmd_undrawn_vertices(ctx);
- }
-
- firstPtIdx += pathPointCount;
- if (_path_has_curves (ctx, ptrPath)) {
- //skip segments lengths used in stroke
- ptrPath++;
- uint32_t totPts = 0;
- while (totPts < pathPointCount)
- totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
- }else
- ptrPath++;
- }
+// create fill from current path with ear clipping technic
+void _fill_non_zero(VkvgContext ctx) {
+ Vertex v = {{0}, ctx->curColor, {0, 0, -1}};
+
+ uint32_t ptrPath = 0;
+ uint32_t firstPtIdx = 0;
+
+ while (ptrPath < ctx->pathPtr) {
+ uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+
+ if (pathPointCount > 2) {
+ VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+ // ear_clip_point* ecps = (ear_clip_point*)malloc(pathPointCount*sizeof(ear_clip_point));
+ ear_clip_point ecps[pathPointCount];
+ uint32_t ecps_count = pathPointCount;
+ VKVG_IBO_INDEX_TYPE i = 0;
+
+ // init points link list
+ while (i < pathPointCount - 1) {
+ v.pos = ctx->points[i + firstPtIdx];
+ ear_clip_point ecp = {v.pos, firstVertIdx + i, &ecps[i + 1]};
+ ecps[i] = ecp;
+ _add_vertex(ctx, v);
+ i++;
+ }
+
+ v.pos = ctx->points[i + firstPtIdx];
+ ear_clip_point ecp = {v.pos, firstVertIdx + i, ecps};
+ ecps[i] = ecp;
+ _add_vertex(ctx, v);
+
+ ear_clip_point *ecp_current = ecps;
+ uint32_t tries = 0;
+
+ while (ecps_count > 3) {
+ if (tries > ecps_count) {
+ break;
+ }
+ ear_clip_point *v0 = ecp_current->next, *v1 = ecp_current, *v2 = ecp_current->next->next;
+ if (ecp_zcross(v0, v2, v1) < 0) {
+ ecp_current = ecp_current->next;
+ tries++;
+ continue;
+ }
+ ear_clip_point *vP = v2->next;
+ bool isEar = true;
+ while (vP != v1) {
+ if (ptInTriangle(vP->pos, v0->pos, v2->pos, v1->pos)) {
+ isEar = false;
+ break;
+ }
+ vP = vP->next;
+ }
+ if (isEar) {
+ _add_triangle_indices(ctx, v0->idx, v1->idx, v2->idx);
+ v1->next = v2;
+ ecps_count--;
+ tries = 0;
+ } else {
+ ecp_current = ecp_current->next;
+ tries++;
+ }
+ }
+ if (ecps_count == 3)
+ _add_triangle_indices(ctx, ecp_current->next->idx, ecp_current->idx, ecp_current->next->next->idx);
+
+ // limit batch size here to 1/3 of the ibo index type ability
+ if (ctx->vertCount - ctx->curVertOffset > VKVG_IBO_MAX / 3)
+ _emit_draw_cmd_undrawn_vertices(ctx);
+ }
+
+ firstPtIdx += pathPointCount;
+ if (_path_has_curves(ctx, ptrPath)) {
+ // skip segments lengths used in stroke
+ ptrPath++;
+ uint32_t totPts = 0;
+ while (totPts < pathPointCount)
+ totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
+ } else
+ ptrPath++;
+ }
}
#endif
-void _vkvg_path_extents (VkvgContext ctx, bool transformed, float *x1, float *y1, float *x2, float *y2) {
- uint32_t ptrPath = 0;
- uint32_t firstPtIdx = 0;
-
- float xMin = FLT_MAX, yMin = FLT_MAX;
- float xMax = FLT_MIN, yMax = FLT_MIN;
-
- while (ptrPath < ctx->pathPtr){
- uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
-
- for (uint32_t i = firstPtIdx; i < firstPtIdx + pathPointCount; i++){
- vec2 p = ctx->points[i];
- if (transformed)
- vkvg_matrix_transform_point (&ctx->pushConsts.mat, &p.x, &p.y);
- if (p.x < xMin)
- xMin = p.x;
- if (p.x > xMax)
- xMax = p.x;
- if (p.y < yMin)
- yMin = p.y;
- if (p.y > yMax)
- yMax = p.y;
- }
-
- firstPtIdx += pathPointCount;
- if (_path_has_curves (ctx, ptrPath)) {
- //skip segments lengths used in stroke
- ptrPath++;
- uint32_t totPts = 0;
- while (totPts < pathPointCount)
- totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
- }else
- ptrPath++;
- }
- *x1 = xMin;
- *x2 = xMax;
- *y1 = yMin;
- *y2 = yMax;
-}
-
-void _draw_full_screen_quad (VkvgContext ctx, vec4* scissor) {
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_start(ctx->cmd, "_draw_full_screen_quad", DBG_LAB_COLOR_FSQ);
+void _vkvg_path_extents(VkvgContext ctx, bool transformed, float *x1, float *y1, float *x2, float *y2) {
+ uint32_t ptrPath = 0;
+ uint32_t firstPtIdx = 0;
+
+ float xMin = FLT_MAX, yMin = FLT_MAX;
+ float xMax = FLT_MIN, yMax = FLT_MIN;
+
+ while (ptrPath < ctx->pathPtr) {
+ uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+
+ for (uint32_t i = firstPtIdx; i < firstPtIdx + pathPointCount; i++) {
+ vec2 p = ctx->points[i];
+ if (transformed)
+ vkvg_matrix_transform_point(&ctx->pushConsts.mat, &p.x, &p.y);
+ if (p.x < xMin)
+ xMin = p.x;
+ if (p.x > xMax)
+ xMax = p.x;
+ if (p.y < yMin)
+ yMin = p.y;
+ if (p.y > yMax)
+ yMax = p.y;
+ }
+
+ firstPtIdx += pathPointCount;
+ if (_path_has_curves(ctx, ptrPath)) {
+ // skip segments lengths used in stroke
+ ptrPath++;
+ uint32_t totPts = 0;
+ while (totPts < pathPointCount)
+ totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
+ } else
+ ptrPath++;
+ }
+ *x1 = xMin;
+ *x2 = xMax;
+ *y1 = yMin;
+ *y2 = yMax;
+}
+
+void _draw_full_screen_quad(VkvgContext ctx, vec4 *scissor) {
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_start(ctx->cmd, "_draw_full_screen_quad", DBG_LAB_COLOR_FSQ);
#endif
- if (scissor) {
- VkRect2D r = {
- {(int32_t)MAX(scissor->xMin, 0), (int32_t)MAX(scissor->yMin, 0)},
- {(int32_t)MAX(scissor->xMax - (int32_t)scissor->xMin + 1, 1), (int32_t)MAX(scissor->yMax - (int32_t)scissor->yMin + 1, 1)}
- };
- CmdSetScissor(ctx->cmd, 0, 1, &r);
- }
-
- uint32_t firstVertIdx = ctx->vertCount;
- _ensure_vertex_cache_size (ctx, 3);
-
- _add_vertexf_unchecked (ctx, -1, -1);
- _add_vertexf_unchecked (ctx, 3, -1);
- _add_vertexf_unchecked (ctx, -1, 3);
-
- ctx->curVertOffset = ctx->vertCount;
-
- ctx->pushConsts.fsq_patternType |= FULLSCREEN_BIT;
- CmdPushConstants(ctx->cmd, ctx->dev->pipelineLayout,
- VK_SHADER_STAGE_VERTEX_BIT, 24, 4,&ctx->pushConsts.fsq_patternType);
- CmdDraw (ctx->cmd,3,1,firstVertIdx,0);
- ctx->pushConsts.fsq_patternType &= ~FULLSCREEN_BIT;
- CmdPushConstants(ctx->cmd, ctx->dev->pipelineLayout,
- VK_SHADER_STAGE_VERTEX_BIT, 24, 4,&ctx->pushConsts.fsq_patternType);
- if (scissor)
- CmdSetScissor(ctx->cmd, 0, 1, &ctx->bounds);
-
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_cmd_label_end (ctx->cmd);
+ if (scissor) {
+ VkRect2D r = {{(int32_t)MAX(scissor->xMin, 0), (int32_t)MAX(scissor->yMin, 0)},
+ {(int32_t)MAX(scissor->xMax - (int32_t)scissor->xMin + 1, 1),
+ (int32_t)MAX(scissor->yMax - (int32_t)scissor->yMin + 1, 1)}};
+ CmdSetScissor(ctx->cmd, 0, 1, &r);
+ }
+
+ uint32_t firstVertIdx = ctx->vertCount;
+ _ensure_vertex_cache_size(ctx, 3);
+
+ _add_vertexf_unchecked(ctx, -1, -1);
+ _add_vertexf_unchecked(ctx, 3, -1);
+ _add_vertexf_unchecked(ctx, -1, 3);
+
+ ctx->curVertOffset = ctx->vertCount;
+
+ ctx->pushConsts.fsq_patternType |= FULLSCREEN_BIT;
+ CmdPushConstants(ctx->cmd, ctx->dev->pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 24, 4,
+ &ctx->pushConsts.fsq_patternType);
+ CmdDraw(ctx->cmd, 3, 1, firstVertIdx, 0);
+ ctx->pushConsts.fsq_patternType &= ~FULLSCREEN_BIT;
+ CmdPushConstants(ctx->cmd, ctx->dev->pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 24, 4,
+ &ctx->pushConsts.fsq_patternType);
+ if (scissor)
+ CmdSetScissor(ctx->cmd, 0, 1, &ctx->bounds);
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_end(ctx->cmd);
#endif
}
-void _select_font_face (VkvgContext ctx, const char* name){
- if (strcmp(ctx->selectedFontName, name) == 0)
- return;
- strcpy (ctx->selectedFontName, name);
- ctx->currentFont = NULL;
- ctx->currentFontSize = NULL;
+void _select_font_face(VkvgContext ctx, const char *name) {
+ if (strcmp(ctx->selectedFontName, name) == 0)
+ return;
+ strcpy(ctx->selectedFontName, name);
+ ctx->currentFont = NULL;
+ ctx->currentFontSize = NULL;
}
#include "vkvg_fonts.h"
#if VKVG_RECORDING
- #include "recording/vkvg_record_internal.h"
+#include "recording/vkvg_record_internal.h"
#else
- #define RECORD(ctx,cmd,...)
- #define RECORD2(ctx,cmd,...)
+#define RECORD(ctx, cmd, ...)
+#define RECORD2(ctx, cmd, ...)
#endif
-#define VKVG_PTS_SIZE 1024
-#define VKVG_VBO_SIZE (VKVG_PTS_SIZE * 4)
-#define VKVG_IBO_SIZE (VKVG_VBO_SIZE * 6)
-#define VKVG_PATHES_SIZE 16
-#define VKVG_ARRAY_THRESHOLD 8
+#define VKVG_PTS_SIZE 1024
+#define VKVG_VBO_SIZE (VKVG_PTS_SIZE * 4)
+#define VKVG_IBO_SIZE (VKVG_VBO_SIZE * 6)
+#define VKVG_PATHES_SIZE 16
+#define VKVG_ARRAY_THRESHOLD 8
-#define VKVG_IBO_16 0
-#define VKVG_IBO_32 1
+#define VKVG_IBO_16 0
+#define VKVG_IBO_32 1
-#define VKVG_CUR_IBO_TYPE VKVG_IBO_32//change this only
+#define VKVG_CUR_IBO_TYPE VKVG_IBO_32 // change this only
#if VKVG_CUR_IBO_TYPE == VKVG_IBO_16
- #define VKVG_IBO_MAX UINT16_MAX
- #define VKVG_IBO_INDEX_TYPE uint16_t
- #define VKVG_VK_INDEX_TYPE VK_INDEX_TYPE_UINT16
+#define VKVG_IBO_MAX UINT16_MAX
+#define VKVG_IBO_INDEX_TYPE uint16_t
+#define VKVG_VK_INDEX_TYPE VK_INDEX_TYPE_UINT16
#else
- #define VKVG_IBO_MAX UINT32_MAX
- #define VKVG_IBO_INDEX_TYPE uint32_t
- #define VKVG_VK_INDEX_TYPE VK_INDEX_TYPE_UINT32
+#define VKVG_IBO_MAX UINT32_MAX
+#define VKVG_IBO_INDEX_TYPE uint32_t
+#define VKVG_VK_INDEX_TYPE VK_INDEX_TYPE_UINT32
#endif
-#define FULLSCREEN_BIT 0x10000000
-#define SRCTYPE_MASK 0x000000FF
+#define FULLSCREEN_BIT 0x10000000
+#define SRCTYPE_MASK 0x000000FF
#define CreateRgba(r, g, b, a) ((a << 24) | (r << 16) | (g << 8) | b)
#ifdef VKVG_PREMULT_ALPHA
- #define CreateRgbaf(r, g, b, a) (((int)(a * 255.0f) << 24) | ((int)(b * a * 255.0f) << 16) | ((int)(g * a * 255.0f) << 8) | (int)(r * a * 255.0f))
+#define CreateRgbaf(r, g, b, a) \
+ (((int)(a * 255.0f) << 24) | ((int)(b * a * 255.0f) << 16) | ((int)(g * a * 255.0f) << 8) | (int)(r * a * 255.0f))
#else
- #define CreateRgbaf(r, g, b, a) (((int)(a * 255.0f) << 24) | ((int)(b * 255.0f) << 16) | ((int)(g * 255.0f) << 8) | (int)(r * 255.0f))
+#define CreateRgbaf(r, g, b, a) \
+ (((int)(a * 255.0f) << 24) | ((int)(b * 255.0f) << 16) | ((int)(g * 255.0f) << 8) | (int)(r * 255.0f))
#endif
typedef struct {
- vec2 pos;
- uint32_t color;
- vec3 uv;
+ vec2 pos;
+ uint32_t color;
+ vec3 uv;
} Vertex;
typedef struct {
- vec4 source;
- vec2 size;
- uint32_t fsq_patternType;
- float opacity;
- vkvg_matrix_t mat;
- vkvg_matrix_t matInv;
+ vec4 source;
+ vec2 size;
+ uint32_t fsq_patternType;
+ float opacity;
+ vkvg_matrix_t mat;
+ vkvg_matrix_t matInv;
} push_constants;
/* context.curClipState may be one of the following, it's set
* - clip_saved: context is clipped and the clip region is saved at that level.
*/
typedef enum {
- vkvg_clip_state_none = 0x00,
- vkvg_clip_state_clear = 0x01,
- vkvg_clip_state_clip = 0x02,
- vkvg_clip_state_clip_saved = 0x06,
+ vkvg_clip_state_none = 0x00,
+ vkvg_clip_state_clear = 0x01,
+ vkvg_clip_state_clip = 0x02,
+ vkvg_clip_state_clip_saved = 0x06,
} vkvg_clip_state_t;
typedef struct _vkvg_context_save_t {
- struct _vkvg_context_save_t* pNext;
-
- float lineWidth;
- float miterLimit;
- uint32_t dashCount; //value count in dash array, 0 if dash not set.
- float dashOffset; //an offset for dash
- float* dashes; //an array of alternate lengths of on and off stroke.
-
- vkvg_operator_t curOperator;
- vkvg_line_cap_t lineCap;
- vkvg_line_join_t lineJoint;
- vkvg_fill_rule_t curFillRule;
-
- long selectedCharSize; /* Font size*/
- char selectedFontName[FONT_NAME_MAX_SIZE];
- _vkvg_font_identity_t selectedFont; //hold current face and size before cache addition
- _vkvg_font_identity_t* currentFont; //font ready for lookup
- vkvg_direction_t textDirection;
- push_constants pushConsts;
- uint32_t curColor;
- VkvgPattern pattern;
- vkvg_clip_state_t clippingState;
+ struct _vkvg_context_save_t *pNext;
+
+ float lineWidth;
+ float miterLimit;
+ uint32_t dashCount; // value count in dash array, 0 if dash not set.
+ float dashOffset; // an offset for dash
+ float *dashes; // an array of alternate lengths of on and off stroke.
+
+ vkvg_operator_t curOperator;
+ vkvg_line_cap_t lineCap;
+ vkvg_line_join_t lineJoint;
+ vkvg_fill_rule_t curFillRule;
+
+ long selectedCharSize; /* Font size*/
+ char selectedFontName[FONT_NAME_MAX_SIZE];
+ _vkvg_font_identity_t selectedFont; // hold current face and size before cache addition
+ _vkvg_font_identity_t *currentFont; // font ready for lookup
+ vkvg_direction_t textDirection;
+ push_constants pushConsts;
+ uint32_t curColor;
+ VkvgPattern pattern;
+ vkvg_clip_state_t clippingState;
} vkvg_context_save_t;
typedef struct _vkvg_context_t {
- vkvg_status_t status;
- uint32_t references; //reference count
+ vkvg_status_t status;
+ uint32_t references; // reference count
- VkvgDevice dev;
- VkvgSurface pSurf; //surface bound to context, set on creation of ctx
+ VkvgDevice dev;
+ VkvgSurface pSurf; // surface bound to context, set on creation of ctx
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- uint64_t timelineStep; //context cmd last submission timeline id.
+ uint64_t timelineStep; // context cmd last submission timeline id.
#else
- VkFence flushFence; //context fence
+ VkFence flushFence; // context fence
#endif
- //VkDescriptorImageInfo sourceDescriptor; //Store view/sampler in context
+ // VkDescriptorImageInfo sourceDescriptor; //Store view/sampler in context
- VkCommandPool cmdPool; //local pools ensure thread safety
- VkCommandBuffer cmdBuffers[2]; //double cmd buff for context operations
- VkCommandBuffer cmd; //current recording buffer
- bool cmdStarted; //prevent flushing empty renderpass
- bool pushCstDirty; //prevent pushing to gpu if not requested
- VkDescriptorPool descriptorPool; //one pool per thread
- VkDescriptorSet dsFont; //fonts glyphs texture atlas descriptor (local for thread safety)
- VkDescriptorSet dsSrc; //source ds
- VkDescriptorSet dsGrad; //gradient uniform buffer
+ VkCommandPool cmdPool; // local pools ensure thread safety
+ VkCommandBuffer cmdBuffers[2]; // double cmd buff for context operations
+ VkCommandBuffer cmd; // current recording buffer
+ bool cmdStarted; // prevent flushing empty renderpass
+ bool pushCstDirty; // prevent pushing to gpu if not requested
+ VkDescriptorPool descriptorPool; // one pool per thread
+ VkDescriptorSet dsFont; // fonts glyphs texture atlas descriptor (local for thread safety)
+ VkDescriptorSet dsSrc; // source ds
+ VkDescriptorSet dsGrad; // gradient uniform buffer
- VkhImage fontCacheImg; //current font cache, may not be the last one, updated only if new glyphs are
- //uploaded by the current context
+ VkhImage fontCacheImg; // current font cache, may not be the last one, updated only if new glyphs are
+ // uploaded by the current context
- VkRect2D bounds;
+ VkRect2D bounds;
- uint32_t curColor;
+ uint32_t curColor;
#if VKVG_FILL_NZ_GLUTESS
- void (*vertex_cb)(VKVG_IBO_INDEX_TYPE, VkvgContext);//tesselator vertex callback
- VKVG_IBO_INDEX_TYPE tesselator_fan_start;
- uint32_t tesselator_idx_counter;
+ void (*vertex_cb)(VKVG_IBO_INDEX_TYPE, VkvgContext); // tesselator vertex callback
+ VKVG_IBO_INDEX_TYPE tesselator_fan_start;
+ uint32_t tesselator_idx_counter;
#endif
#if VKVG_RECORDING
- vkvg_recording_t* recording;
+ vkvg_recording_t *recording;
#endif
- vkh_buffer_t uboGrad; //uniform buff obj holdings gradient infos
-
- //vk buffers, holds data until flush
- vkh_buffer_t indices; //index buffer with persistent map memory
- uint32_t sizeIBO; //size of vk ibo
- uint32_t sizeIndices; //reserved size
- uint32_t indCount; //current indice count
-
- uint32_t curIndStart; //last index recorded in cmd buff
- VKVG_IBO_INDEX_TYPE curVertOffset; //vertex offset in draw indexed command
-
- vkh_buffer_t vertices; //vertex buffer with persistent mapped memory
- uint32_t sizeVBO; //size of vk vbo size
- uint32_t sizeVertices; //reserved size
- uint32_t vertCount; //effective vertices count
-
- Vertex* vertexCache;
- VKVG_IBO_INDEX_TYPE* indexCache;
-
- //pathes, exists until stroke of fill
- vec2* points; //points array
- uint32_t sizePoints; //reserved size
- uint32_t pointCount; //effective points count
-
- //pathes array is a list of point count per segment
- uint32_t pathPtr; //pointer in the path array
- uint32_t* pathes;
- uint32_t sizePathes;
-
- uint32_t segmentPtr; //current segment count in current path having curves
- uint32_t subpathCount; //store count of subpath, not straight forward to retrieve from segmented path array
- bool simpleConvex; //true if path is single rect or concave closed curve.
-
- float lineWidth;
- float miterLimit;
- uint32_t dashCount; //value count in dash array, 0 if dash not set.
- float dashOffset; //an offset for dash
- float* dashes; //an array of alternate lengths of on and off stroke.
-
- vkvg_operator_t curOperator;
- vkvg_line_cap_t lineCap;
- vkvg_line_join_t lineJoin;
- vkvg_fill_rule_t curFillRule;
-
- long selectedCharSize; /* Font size*/
- char selectedFontName[FONT_NAME_MAX_SIZE];
- //_vkvg_font_t selectedFont; //hold current face and size before cache addition
- _vkvg_font_identity_t* currentFont; //font pointing to cached fonts identity
- _vkvg_font_t* currentFontSize; //font structure by size ready for lookup
- vkvg_direction_t textDirection;
-
- push_constants pushConsts;
- VkvgPattern pattern;
-
- vkvg_context_save_t* pSavedCtxs; //last ctx saved ptr
- uint8_t curSavBit; //current stencil bit used to save context, 6 bits used by stencil for save/restore
- VkhImage* savedStencils; //additional image for saving contexes once more than 6 save/restore are reached
- vkvg_clip_state_t curClipState; //current clipping status relative to the previous saved one or clear state if none.
-
- VkClearRect clearRect;
- VkRenderPassBeginInfo renderPassBeginInfo;
+ vkh_buffer_t uboGrad; // uniform buff obj holdings gradient infos
+
+ // vk buffers, holds data until flush
+ vkh_buffer_t indices; // index buffer with persistent map memory
+ uint32_t sizeIBO; // size of vk ibo
+ uint32_t sizeIndices; // reserved size
+ uint32_t indCount; // current indice count
+
+ uint32_t curIndStart; // last index recorded in cmd buff
+ VKVG_IBO_INDEX_TYPE curVertOffset; // vertex offset in draw indexed command
+
+ vkh_buffer_t vertices; // vertex buffer with persistent mapped memory
+ uint32_t sizeVBO; // size of vk vbo size
+ uint32_t sizeVertices; // reserved size
+ uint32_t vertCount; // effective vertices count
+
+ Vertex *vertexCache;
+ VKVG_IBO_INDEX_TYPE *indexCache;
+
+ // pathes, exists until stroke of fill
+ vec2 *points; // points array
+ uint32_t sizePoints; // reserved size
+ uint32_t pointCount; // effective points count
+
+ // pathes array is a list of point count per segment
+ uint32_t pathPtr; // pointer in the path array
+ uint32_t *pathes;
+ uint32_t sizePathes;
+
+ uint32_t segmentPtr; // current segment count in current path having curves
+ uint32_t subpathCount; // store count of subpath, not straight forward to retrieve from segmented path array
+ bool simpleConvex; // true if path is single rect or concave closed curve.
+
+ float lineWidth;
+ float miterLimit;
+ uint32_t dashCount; // value count in dash array, 0 if dash not set.
+ float dashOffset; // an offset for dash
+ float *dashes; // an array of alternate lengths of on and off stroke.
+
+ vkvg_operator_t curOperator;
+ vkvg_line_cap_t lineCap;
+ vkvg_line_join_t lineJoin;
+ vkvg_fill_rule_t curFillRule;
+
+ long selectedCharSize; /* Font size*/
+ char selectedFontName[FONT_NAME_MAX_SIZE];
+ //_vkvg_font_t selectedFont; //hold current face and size before cache addition
+ _vkvg_font_identity_t *currentFont; // font pointing to cached fonts identity
+ _vkvg_font_t *currentFontSize; // font structure by size ready for lookup
+ vkvg_direction_t textDirection;
+
+ push_constants pushConsts;
+ VkvgPattern pattern;
+
+ vkvg_context_save_t *pSavedCtxs; // last ctx saved ptr
+ uint8_t curSavBit; // current stencil bit used to save context, 6 bits used by stencil for save/restore
+ VkhImage *savedStencils; // additional image for saving contexes once more than 6 save/restore are reached
+ vkvg_clip_state_t curClipState; // current clipping status relative to the previous saved one or clear state if
+ // none.
+
+ VkClearRect clearRect;
+ VkRenderPassBeginInfo renderPassBeginInfo;
} vkvg_context;
typedef struct _ear_clip_point {
- vec2 pos;
- VKVG_IBO_INDEX_TYPE idx;
- struct _ear_clip_point* next;
+ vec2 pos;
+ VKVG_IBO_INDEX_TYPE idx;
+ struct _ear_clip_point *next;
} ear_clip_point;
typedef struct {
- bool dashOn;
- uint32_t curDash; //current dash index
- float curDashOffset; //cur dash offset between defined path point and last dash segment(on/off) start
- float totDashLength; //total length of dashes
- vec2 normal;
+ bool dashOn;
+ uint32_t curDash; // current dash index
+ float curDashOffset; // cur dash offset between defined path point and last dash segment(on/off) start
+ float totDashLength; // total length of dashes
+ vec2 normal;
} dash_context_t;
typedef struct {
- uint32_t iL;
- uint32_t iR;
- uint32_t cp;//current point
-
- VKVG_IBO_INDEX_TYPE firstIdx;//save first point idx for closed path
- float hw; //stroke half width, computed once.
- float lhMax; //miter limit * line width
- float arcStep; //cached arcStep, prevent compute multiple times for same stroke, 0 if not yet computed
+ uint32_t iL;
+ uint32_t iR;
+ uint32_t cp; // current point
+
+ VKVG_IBO_INDEX_TYPE firstIdx; // save first point idx for closed path
+ float hw; // stroke half width, computed once.
+ float lhMax; // miter limit * line width
+ float arcStep; // cached arcStep, prevent compute multiple times for same stroke, 0 if not yet computed
} stroke_context_t;
-void _check_vertex_cache_size (VkvgContext ctx);
-void _ensure_vertex_cache_size (VkvgContext ctx, uint32_t addedVerticesCount);
-void _resize_vertex_cache (VkvgContext ctx, uint32_t newSize);
-
-void _check_index_cache_size (VkvgContext ctx);
-void _ensure_index_cache_size (VkvgContext ctx, uint32_t addedIndicesCount);
-void _resize_index_cache (VkvgContext ctx, uint32_t newSize);
-
-bool _check_pathes_array (VkvgContext ctx);
-
-bool _current_path_is_empty (VkvgContext ctx);
-void _finish_path (VkvgContext ctx);
-void _clear_path (VkvgContext ctx);
-void _remove_last_point (VkvgContext ctx);
-bool _path_is_closed (VkvgContext ctx, uint32_t ptrPath);
-void _set_curve_start (VkvgContext ctx);
-void _set_curve_end (VkvgContext ctx);
-bool _path_has_curves (VkvgContext ctx, uint32_t ptrPath);
-
-float _normalizeAngle (float a);
-float _get_arc_step (VkvgContext ctx, float radius);
-
-vec2 _get_current_position (VkvgContext ctx);
-void _add_point (VkvgContext ctx, float x, float y);
-
-void _resetMinMax (VkvgContext ctx);
-void _vkvg_path_extents (VkvgContext ctx, bool transformed, float *x1, float *y1, float *x2, float *y2);
-void _draw_stoke_cap (VkvgContext ctx, stroke_context_t* str, vec2 p0, vec2 n, bool isStart);
-void _draw_segment (VkvgContext ctx, stroke_context_t* str, dash_context_t* dc, bool isCurve);
-float _draw_dashed_segment (VkvgContext ctx, stroke_context_t *str, dash_context_t* dc, bool isCurve);
-bool _build_vb_step (VkvgContext ctx, stroke_context_t *str, bool isCurve);
-
-void _poly_fill (VkvgContext ctx, vec4 *bounds);
-void _fill_non_zero (VkvgContext ctx);
-void _draw_full_screen_quad (VkvgContext ctx, vec4 *scissor);
-
-void _create_gradient_buff (VkvgContext ctx);
-void _create_vertices_buff (VkvgContext ctx);
-void _add_vertex (VkvgContext ctx, Vertex v);
-void _add_vertexf (VkvgContext ctx, float x, float y);
-void _set_vertex (VkvgContext ctx, uint32_t idx, Vertex v);
-void _add_triangle_indices (VkvgContext ctx, VKVG_IBO_INDEX_TYPE i0, VKVG_IBO_INDEX_TYPE i1, VKVG_IBO_INDEX_TYPE i2);
-void _add_tri_indices_for_rect (VkvgContext ctx, VKVG_IBO_INDEX_TYPE i);
-
-void _vao_add_rectangle (VkvgContext ctx, float x, float y, float width, float height);
-
-void _bind_draw_pipeline (VkvgContext ctx);
-void _create_cmd_buff (VkvgContext ctx);
-void _check_vao_size (VkvgContext ctx);
-void _flush_cmd_buff (VkvgContext ctx);
-void _ensure_renderpass_is_started (VkvgContext ctx);
-void _emit_draw_cmd_undrawn_vertices (VkvgContext ctx);
-void _flush_cmd_until_vx_base (VkvgContext ctx);
-bool _wait_ctx_flush_end (VkvgContext ctx);
-bool _wait_and_submit_cmd (VkvgContext ctx);
-void _update_push_constants (VkvgContext ctx);
-void _update_cur_pattern (VkvgContext ctx, VkvgPattern pat);
-void _set_mat_inv_and_vkCmdPush (VkvgContext ctx);
-void _start_cmd_for_render_pass (VkvgContext ctx);
-
-void _createDescriptorPool (VkvgContext ctx);
-void _init_descriptor_sets (VkvgContext ctx);
-void _update_descriptor_set (VkvgContext ctx, VkhImage img, VkDescriptorSet ds);
-void _update_gradient_desc_set (VkvgContext ctx);
-void _free_ctx_save (vkvg_context_save_t* sav);
+void _check_vertex_cache_size(VkvgContext ctx);
+void _ensure_vertex_cache_size(VkvgContext ctx, uint32_t addedVerticesCount);
+void _resize_vertex_cache(VkvgContext ctx, uint32_t newSize);
+
+void _check_index_cache_size(VkvgContext ctx);
+void _ensure_index_cache_size(VkvgContext ctx, uint32_t addedIndicesCount);
+void _resize_index_cache(VkvgContext ctx, uint32_t newSize);
+
+bool _check_pathes_array(VkvgContext ctx);
+
+bool _current_path_is_empty(VkvgContext ctx);
+void _finish_path(VkvgContext ctx);
+void _clear_path(VkvgContext ctx);
+void _remove_last_point(VkvgContext ctx);
+bool _path_is_closed(VkvgContext ctx, uint32_t ptrPath);
+void _set_curve_start(VkvgContext ctx);
+void _set_curve_end(VkvgContext ctx);
+bool _path_has_curves(VkvgContext ctx, uint32_t ptrPath);
+
+float _normalizeAngle(float a);
+float _get_arc_step(VkvgContext ctx, float radius);
+
+vec2 _get_current_position(VkvgContext ctx);
+void _add_point(VkvgContext ctx, float x, float y);
+
+void _resetMinMax(VkvgContext ctx);
+void _vkvg_path_extents(VkvgContext ctx, bool transformed, float *x1, float *y1, float *x2, float *y2);
+void _draw_stoke_cap(VkvgContext ctx, stroke_context_t *str, vec2 p0, vec2 n, bool isStart);
+void _draw_segment(VkvgContext ctx, stroke_context_t *str, dash_context_t *dc, bool isCurve);
+float _draw_dashed_segment(VkvgContext ctx, stroke_context_t *str, dash_context_t *dc, bool isCurve);
+bool _build_vb_step(VkvgContext ctx, stroke_context_t *str, bool isCurve);
+
+void _poly_fill(VkvgContext ctx, vec4 *bounds);
+void _fill_non_zero(VkvgContext ctx);
+void _draw_full_screen_quad(VkvgContext ctx, vec4 *scissor);
+
+void _create_gradient_buff(VkvgContext ctx);
+void _create_vertices_buff(VkvgContext ctx);
+void _add_vertex(VkvgContext ctx, Vertex v);
+void _add_vertexf(VkvgContext ctx, float x, float y);
+void _set_vertex(VkvgContext ctx, uint32_t idx, Vertex v);
+void _add_triangle_indices(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i0, VKVG_IBO_INDEX_TYPE i1, VKVG_IBO_INDEX_TYPE i2);
+void _add_tri_indices_for_rect(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i);
+
+void _vao_add_rectangle(VkvgContext ctx, float x, float y, float width, float height);
+
+void _bind_draw_pipeline(VkvgContext ctx);
+void _create_cmd_buff(VkvgContext ctx);
+void _check_vao_size(VkvgContext ctx);
+void _flush_cmd_buff(VkvgContext ctx);
+void _ensure_renderpass_is_started(VkvgContext ctx);
+void _emit_draw_cmd_undrawn_vertices(VkvgContext ctx);
+void _flush_cmd_until_vx_base(VkvgContext ctx);
+bool _wait_ctx_flush_end(VkvgContext ctx);
+bool _wait_and_submit_cmd(VkvgContext ctx);
+void _update_push_constants(VkvgContext ctx);
+void _update_cur_pattern(VkvgContext ctx, VkvgPattern pat);
+void _set_mat_inv_and_vkCmdPush(VkvgContext ctx);
+void _start_cmd_for_render_pass(VkvgContext ctx);
+
+void _createDescriptorPool(VkvgContext ctx);
+void _init_descriptor_sets(VkvgContext ctx);
+void _update_descriptor_set(VkvgContext ctx, VkhImage img, VkDescriptorSet ds);
+void _update_gradient_desc_set(VkvgContext ctx);
+void _free_ctx_save(vkvg_context_save_t *sav);
void _release_context_ressources(VkvgContext ctx);
-static inline float vec2_zcross (vec2 v1, vec2 v2){
- return v1.x*v2.y-v1.y*v2.x;
+static inline float vec2_zcross(vec2 v1, vec2 v2) { return v1.x * v2.y - v1.y * v2.x; }
+static inline float ecp_zcross(ear_clip_point *p0, ear_clip_point *p1, ear_clip_point *p2) {
+ return vec2_zcross(vec2_sub(p1->pos, p0->pos), vec2_sub(p2->pos, p0->pos));
}
-static inline float ecp_zcross (ear_clip_point* p0, ear_clip_point* p1, ear_clip_point* p2){
- return vec2_zcross (vec2_sub (p1->pos, p0->pos), vec2_sub (p2->pos, p0->pos));
-}
-void _recursive_bezier(VkvgContext ctx, float distanceTolerance,
- float x1, float y1, float x2, float y2,
- float x3, float y3, float x4, float y4,
- unsigned level);
-void _bezier (VkvgContext ctx,
- float x1, float y1, float x2, float y2,
- float x3, float y3, float x4, float y4);
-void _line_to (VkvgContext ctx, float x, float y);
-void _elliptic_arc (VkvgContext ctx, float x1, float y1, float x2, float y2,
- bool largeArc, bool counterClockWise, float _rx, float _ry, float phi);
-
-void _select_font_face (VkvgContext ctx, const char* name);
+void _recursive_bezier(VkvgContext ctx, float distanceTolerance, float x1, float y1, float x2, float y2, float x3,
+ float y3, float x4, float y4, unsigned level);
+void _bezier(VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4);
+void _line_to(VkvgContext ctx, float x, float y);
+void _elliptic_arc(VkvgContext ctx, float x1, float y1, float x2, float y2, bool largeArc, bool counterClockWise,
+ float _rx, float _ry, float phi);
+
+void _select_font_face(VkvgContext ctx, const char *name);
#endif
#include "vkh_phyinfo.h"
#include "vk_mem_alloc.h"
-#define TRY_LOAD_DEVICE_EXT(ext) { \
-if (vkh_phyinfo_try_get_extension_properties(pi, #ext, NULL)) \
- enabledExts[enabledExtsCount++] = #ext; \
-}
-void vkvg_device_set_context_cache_size (VkvgDevice dev, uint32_t maxCount) {
- if (maxCount == dev->cachedContextMaxCount)
- return;
-
- dev->cachedContextMaxCount = maxCount;
-
- _cached_ctx* cur = dev->cachedContextLast;
- while (cur && dev->cachedContextCount > dev->cachedContextMaxCount) {
- _release_context_ressources (cur->ctx);
- _cached_ctx* prev = cur;
- cur = cur->pNext;
- free (prev);
- dev->cachedContextCount--;
- }
- dev->cachedContextLast = cur;
+#define TRY_LOAD_DEVICE_EXT(ext) \
+ { \
+ if (vkh_phyinfo_try_get_extension_properties(pi, #ext, NULL)) \
+ enabledExts[enabledExtsCount++] = #ext; \
+ }
+void vkvg_device_set_context_cache_size(VkvgDevice dev, uint32_t maxCount) {
+ if (maxCount == dev->cachedContextMaxCount)
+ return;
+
+ dev->cachedContextMaxCount = maxCount;
+
+ _cached_ctx *cur = dev->cachedContextLast;
+ while (cur && dev->cachedContextCount > dev->cachedContextMaxCount) {
+ _release_context_ressources(cur->ctx);
+ _cached_ctx *prev = cur;
+ cur = cur->pNext;
+ free(prev);
+ dev->cachedContextCount--;
+ }
+ dev->cachedContextLast = cur;
}
-void _device_init (VkvgDevice dev, const vkvg_device_create_info_t* info) {
- dev->vkDev = info->vkdev;
- dev->phy = info->phy;
+void _device_init(VkvgDevice dev, const vkvg_device_create_info_t *info) {
+ dev->vkDev = info->vkdev;
+ dev->phy = info->phy;
dev->instance = info->inst;
- dev->hdpi = 72;
- dev->vdpi = 72;
- dev->samples= info->samples;
- if (dev->samples == VK_SAMPLE_COUNT_1_BIT)
- dev->deferredResolve = false;
+ dev->hdpi = 72;
+ dev->vdpi = 72;
+ dev->samples = info->samples;
+ if (dev->samples == VK_SAMPLE_COUNT_1_BIT)
+ dev->deferredResolve = false;
else
dev->deferredResolve = info->deferredResolve;
- dev->cachedContextMaxCount = VKVG_MAX_CACHED_CONTEXT_COUNT;
+ dev->cachedContextMaxCount = VKVG_MAX_CACHED_CONTEXT_COUNT;
#if VKVG_DBG_STATS
- dev->debug_stats = (vkvg_debug_stats_t) {0};
+ dev->debug_stats = (vkvg_debug_stats_t){0};
#endif
- VkFormat format = FB_COLOR_FORMAT;
+ VkFormat format = FB_COLOR_FORMAT;
- _device_check_best_image_tiling(dev, format);
- if (dev->status != VKVG_STATUS_SUCCESS)
- return;
+ _device_check_best_image_tiling(dev, format);
+ if (dev->status != VKVG_STATUS_SUCCESS)
+ return;
- if (!_device_init_function_pointers (dev)){
- dev->status = VKVG_STATUS_NULL_POINTER;
- return;
- }
+ if (!_device_init_function_pointers(dev)) {
+ dev->status = VKVG_STATUS_NULL_POINTER;
+ return;
+ }
- VkhPhyInfo phyInfos = vkh_phyinfo_create (dev->phy, NULL);
+ VkhPhyInfo phyInfos = vkh_phyinfo_create(dev->phy, NULL);
dev->phyMemProps = phyInfos->memProps;
- dev->gQueue = vkh_queue_create ((VkhDevice)dev, info->qFamIdx, info->qIndex);
- //mtx_init (&dev->gQMutex, mtx_plain);
+ dev->gQueue = vkh_queue_create((VkhDevice)dev, info->qFamIdx, info->qIndex);
+ // mtx_init (&dev->gQMutex, mtx_plain);
- vkh_phyinfo_destroy (phyInfos);
+ vkh_phyinfo_destroy(phyInfos);
#ifdef VKH_USE_VMA
- VmaAllocatorCreateInfo allocatorInfo = {
- .physicalDevice = info->phy,
- .device = info->vkdev
- };
- vmaCreateAllocator(&allocatorInfo, (VmaAllocator*)&dev->allocator);
+ VmaAllocatorCreateInfo allocatorInfo = {.physicalDevice = info->phy, .device = info->vkdev};
+ vmaCreateAllocator(&allocatorInfo, (VmaAllocator *)&dev->allocator);
#endif
- dev->cmdPool= vkh_cmd_pool_create ((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
- dev->cmd = vkh_cmd_buff_create ((VkhDevice)dev, dev->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
- dev->fence = vkh_fence_create_signaled ((VkhDevice)dev);
-
- _device_create_pipeline_cache (dev);
- _fonts_cache_create (dev);
- if (dev->deferredResolve || dev->samples == VK_SAMPLE_COUNT_1_BIT){
- dev->renderPass = _device_createRenderPassNoResolve (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD);
- dev->renderPass_ClearStencil = _device_createRenderPassNoResolve (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR);
- dev->renderPass_ClearAll = _device_createRenderPassNoResolve (dev, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR);
- }else{
- dev->renderPass = _device_createRenderPassMS (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD);
- dev->renderPass_ClearStencil = _device_createRenderPassMS (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR);
- dev->renderPass_ClearAll = _device_createRenderPassMS (dev, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR);
- }
- _device_createDescriptorSetLayout (dev);
- _device_setupPipelines (dev);
-
- _device_create_empty_texture (dev, format, dev->supportedTiling);
+ dev->cmdPool =
+ vkh_cmd_pool_create((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
+ dev->cmd = vkh_cmd_buff_create((VkhDevice)dev, dev->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ dev->fence = vkh_fence_create_signaled((VkhDevice)dev);
+
+ _device_create_pipeline_cache(dev);
+ _fonts_cache_create(dev);
+ if (dev->deferredResolve || dev->samples == VK_SAMPLE_COUNT_1_BIT) {
+ dev->renderPass =
+ _device_createRenderPassNoResolve(dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD);
+ dev->renderPass_ClearStencil =
+ _device_createRenderPassNoResolve(dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR);
+ dev->renderPass_ClearAll =
+ _device_createRenderPassNoResolve(dev, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR);
+ } else {
+ dev->renderPass = _device_createRenderPassMS(dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD);
+ dev->renderPass_ClearStencil =
+ _device_createRenderPassMS(dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR);
+ dev->renderPass_ClearAll =
+ _device_createRenderPassMS(dev, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR);
+ }
+ _device_createDescriptorSetLayout(dev);
+ _device_setupPipelines(dev);
+
+ _device_create_empty_texture(dev, format, dev->supportedTiling);
#ifdef DEBUG
- #if defined(__linux__) && defined(__GLIBC__)
- _linux_register_error_handler ();
- #endif
- #ifdef VKVG_DBG_UTILS
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_POOL, (uint64_t)dev->cmdPool, "Device Cmd Pool");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)dev->cmd, "Device Cmd Buff");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_FENCE, (uint64_t)dev->fence, "Device Fence");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass, "RP load img/stencil");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass_ClearStencil, "RP clear stencil");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass_ClearAll, "RP clear all");
-
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslSrc, "DSLayout SOURCE");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslFont, "DSLayout FONT");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslGrad, "DSLayout GRADIENT");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)dev->pipelineLayout, "PLLayout dev");
-
- #ifndef __APPLE__
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipelinePolyFill, "PL Poly fill");
- #endif
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipelineClipping, "PL Clipping");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_OVER, "PL draw Over");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_SUB, "PL draw Substract");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_CLEAR, "PL draw Clear");
-
- vkh_image_set_name(dev->emptyImg, "empty IMG");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(dev->emptyImg), "empty IMG VIEW");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(dev->emptyImg), "empty IMG SAMPLER");
- #endif
+#if defined(__linux__) && defined(__GLIBC__)
+ _linux_register_error_handler();
#endif
- dev->status = VKVG_STATUS_SUCCESS;
-}
+#ifdef VKVG_DBG_UTILS
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_POOL, (uint64_t)dev->cmdPool, "Device Cmd Pool");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)dev->cmd, "Device Cmd Buff");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_FENCE, (uint64_t)dev->fence, "Device Fence");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass,
+ "RP load img/stencil");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass_ClearStencil,
+ "RP clear stencil");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass_ClearAll,
+ "RP clear all");
+
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslSrc,
+ "DSLayout SOURCE");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslFont,
+ "DSLayout FONT");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslGrad,
+ "DSLayout GRADIENT");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)dev->pipelineLayout,
+ "PLLayout dev");
-#define _CHECK_INST_EXT(ext)\
-if (vkh_instance_extension_supported(#ext)) { \
- if (pExtensions) \
- pExtensions[*pExtCount] = #ext; \
- (*pExtCount)++; \
+#ifndef __APPLE__
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipelinePolyFill,
+ "PL Poly fill");
+#endif
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipelineClipping, "PL Clipping");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_OVER, "PL draw Over");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_SUB, "PL draw Substract");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_CLEAR, "PL draw Clear");
+
+ vkh_image_set_name(dev->emptyImg, "empty IMG");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(dev->emptyImg),
+ "empty IMG VIEW");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(dev->emptyImg),
+ "empty IMG SAMPLER");
+#endif
+#endif
+ dev->status = VKVG_STATUS_SUCCESS;
}
-void vkvg_get_required_instance_extensions (const char** pExtensions, uint32_t* pExtCount) {
- *pExtCount = 0;
- vkh_instance_extensions_check_init ();
+#define _CHECK_INST_EXT(ext) \
+ if (vkh_instance_extension_supported(#ext)) { \
+ if (pExtensions) \
+ pExtensions[*pExtCount] = #ext; \
+ (*pExtCount)++; \
+ }
+void vkvg_get_required_instance_extensions(const char **pExtensions, uint32_t *pExtCount) {
+ *pExtCount = 0;
+
+ vkh_instance_extensions_check_init();
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- _CHECK_INST_EXT(VK_EXT_debug_utils)
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ _CHECK_INST_EXT(VK_EXT_debug_utils)
#endif
- _CHECK_INST_EXT(VK_KHR_get_physical_device_properties2)
+ _CHECK_INST_EXT(VK_KHR_get_physical_device_properties2)
- vkh_instance_extensions_check_release();
+ vkh_instance_extensions_check_release();
}
-bool _get_dev_extension_is_supported (VkExtensionProperties* pExtensionProperties, uint32_t extensionCount, const char* name) {
- for (uint32_t i=0; i<extensionCount; i++) {
- if (strcmp(name, pExtensionProperties[i].extensionName)==0)
- return true;
- }
- return false;
-}
-#define _CHECK_DEV_EXT(ext) { \
- if (_get_dev_extension_is_supported(pExtensionProperties, extensionCount, #ext)){\
- if (pExtensions) \
- pExtensions[*pExtCount] = #ext; \
- (*pExtCount)++; \
- }\
+bool _get_dev_extension_is_supported(VkExtensionProperties *pExtensionProperties, uint32_t extensionCount,
+ const char *name) {
+ for (uint32_t i = 0; i < extensionCount; i++) {
+ if (strcmp(name, pExtensionProperties[i].extensionName) == 0)
+ return true;
+ }
+ return false;
}
+#define _CHECK_DEV_EXT(ext) \
+ { \
+ if (_get_dev_extension_is_supported(pExtensionProperties, extensionCount, #ext)) { \
+ if (pExtensions) \
+ pExtensions[*pExtCount] = #ext; \
+ (*pExtCount)++; \
+ } \
+ }
-vkvg_status_t vkvg_get_required_device_extensions (VkPhysicalDevice phy, const char** pExtensions, uint32_t* pExtCount) {
- VkExtensionProperties* pExtensionProperties;
- uint32_t extensionCount;
+vkvg_status_t vkvg_get_required_device_extensions(VkPhysicalDevice phy, const char **pExtensions, uint32_t *pExtCount) {
+ VkExtensionProperties *pExtensionProperties;
+ uint32_t extensionCount;
- *pExtCount = 0;
+ *pExtCount = 0;
- VK_CHECK_RESULT(vkEnumerateDeviceExtensionProperties(phy, NULL, &extensionCount, NULL));
- pExtensionProperties = (VkExtensionProperties*)malloc(extensionCount * sizeof(VkExtensionProperties));
- VK_CHECK_RESULT(vkEnumerateDeviceExtensionProperties(phy, NULL, &extensionCount, pExtensionProperties));
+ VK_CHECK_RESULT(vkEnumerateDeviceExtensionProperties(phy, NULL, &extensionCount, NULL));
+ pExtensionProperties = (VkExtensionProperties *)malloc(extensionCount * sizeof(VkExtensionProperties));
+ VK_CHECK_RESULT(vkEnumerateDeviceExtensionProperties(phy, NULL, &extensionCount, pExtensionProperties));
- //https://vulkan.lunarg.com/doc/view/1.2.162.0/mac/1.2-extensions/vkspec.html#VK_KHR_portability_subset
- _CHECK_DEV_EXT(VK_KHR_portability_subset);
- VkPhysicalDeviceFeatures2 phyFeat2 = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
+ // https://vulkan.lunarg.com/doc/view/1.2.162.0/mac/1.2-extensions/vkspec.html#VK_KHR_portability_subset
+ _CHECK_DEV_EXT(VK_KHR_portability_subset);
+ VkPhysicalDeviceFeatures2 phyFeat2 = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
- //ensure feature is implemented by driver.
- VkPhysicalDeviceScalarBlockLayoutFeatures scalarBlockLayoutSupport = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES};
- phyFeat2.pNext = &scalarBlockLayoutSupport;
+ // ensure feature is implemented by driver.
+ VkPhysicalDeviceScalarBlockLayoutFeatures scalarBlockLayoutSupport = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES};
+ phyFeat2.pNext = &scalarBlockLayoutSupport;
#endif
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreSupport = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES};
- timelineSemaphoreSupport.pNext = phyFeat2.pNext;
- phyFeat2.pNext = &timelineSemaphoreSupport;
+ VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreSupport = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES};
+ timelineSemaphoreSupport.pNext = phyFeat2.pNext;
+ phyFeat2.pNext = &timelineSemaphoreSupport;
#endif
- vkGetPhysicalDeviceFeatures2(phy, &phyFeat2);
+ vkGetPhysicalDeviceFeatures2(phy, &phyFeat2);
#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
- if (!scalarBlockLayoutSupport.scalarBlockLayout) {
- LOG(VKVG_LOG_ERR, "CREATE Device failed, vkvg compiled with VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT and feature is not implemented for physical device.\n");
- return VKVG_STATUS_DEVICE_ERROR;
- }
- _CHECK_DEV_EXT(VK_EXT_scalar_block_layout)
+ if (!scalarBlockLayoutSupport.scalarBlockLayout) {
+ LOG(VKVG_LOG_ERR, "CREATE Device failed, vkvg compiled with VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT and feature is "
+ "not implemented for physical device.\n");
+ return VKVG_STATUS_DEVICE_ERROR;
+ }
+ _CHECK_DEV_EXT(VK_EXT_scalar_block_layout)
#endif
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- if (!timelineSemaphoreSupport.timelineSemaphore) {
- LOG(VKVG_LOG_ERR, "CREATE Device failed, VK_SEMAPHORE_TYPE_TIMELINE not supported.\n");
- return VKVG_STATUS_DEVICE_ERROR;
- }
- _CHECK_DEV_EXT(VK_KHR_timeline_semaphore)
+ if (!timelineSemaphoreSupport.timelineSemaphore) {
+ LOG(VKVG_LOG_ERR, "CREATE Device failed, VK_SEMAPHORE_TYPE_TIMELINE not supported.\n");
+ return VKVG_STATUS_DEVICE_ERROR;
+ }
+ _CHECK_DEV_EXT(VK_KHR_timeline_semaphore)
#endif
- return VKVG_STATUS_SUCCESS;
+ return VKVG_STATUS_SUCCESS;
}
-//enabledFeature12 is guarantied to be the first in pNext chain
-const void* vkvg_get_device_requirements (VkPhysicalDeviceFeatures* pEnabledFeatures) {
+// enabledFeature12 is guarantied to be the first in pNext chain
+const void *vkvg_get_device_requirements(VkPhysicalDeviceFeatures *pEnabledFeatures) {
- pEnabledFeatures->fillModeNonSolid = VK_TRUE;
- pEnabledFeatures->sampleRateShading = VK_TRUE;
- pEnabledFeatures->logicOp = VK_TRUE;
+ pEnabledFeatures->fillModeNonSolid = VK_TRUE;
+ pEnabledFeatures->sampleRateShading = VK_TRUE;
+ pEnabledFeatures->logicOp = VK_TRUE;
- void* pNext = NULL;
+ void *pNext = NULL;
#ifdef VK_VERSION_1_2
- static VkPhysicalDeviceVulkan12Features enabledFeatures12 = {
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES
+ static VkPhysicalDeviceVulkan12Features enabledFeatures12 = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES
#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
- ,.scalarBlockLayout = VK_TRUE
+ ,
+ .scalarBlockLayout = VK_TRUE
#endif
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- ,.timelineSemaphore = VK_TRUE
+ ,
+ .timelineSemaphore = VK_TRUE
#endif
- };
- enabledFeatures12.pNext = pNext;
- pNext = &enabledFeatures12;
+ };
+ enabledFeatures12.pNext = pNext;
+ pNext = &enabledFeatures12;
#else
#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
- static VkPhysicalDeviceScalarBlockLayoutFeaturesEXT scalarBlockFeat = {
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT
- ,.scalarBlockLayout = VK_TRUE
- };
- scalarBlockFeat.pNext = pNext;
- pNext = &scalarBlockFeat;
+ static VkPhysicalDeviceScalarBlockLayoutFeaturesEXT scalarBlockFeat = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT, .scalarBlockLayout = VK_TRUE};
+ scalarBlockFeat.pNext = pNext;
+ pNext = &scalarBlockFeat;
#endif
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- static VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timelineSemaFeat = {
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR
- ,.timelineSemaphore = VK_TRUE
- };
- timelineSemaFeat.pNext = pNext;
- pNext = &timelineSemaFeat;
+ static VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timelineSemaFeat = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR, .timelineSemaphore = VK_TRUE};
+ timelineSemaFeat.pNext = pNext;
+ pNext = &timelineSemaFeat;
#endif
#endif
- return pNext;
+ return pNext;
}
+VkvgDevice vkvg_device_create(vkvg_device_create_info_t *info) {
+ LOG(VKVG_LOG_INFO, "CREATE Device\n");
+ VkvgDevice dev = (vkvg_device *)calloc(1, sizeof(vkvg_device));
+ if (!dev) {
+ LOG(VKVG_LOG_ERR, "CREATE Device failed, no memory\n");
+ exit(-1);
+ }
-VkvgDevice vkvg_device_create (vkvg_device_create_info_t* info) {
- LOG(VKVG_LOG_INFO, "CREATE Device\n");
- VkvgDevice dev = (vkvg_device*)calloc(1,sizeof(vkvg_device));
- if (!dev) {
- LOG(VKVG_LOG_ERR, "CREATE Device failed, no memory\n");
- exit(-1);
- }
-
- dev->references = 1;
+ dev->references = 1;
if (!info->vkdev) {
- const char* enabledExts [10];
- const char* enabledLayers[10];
- uint32_t enabledExtsCount = 0, enabledLayersCount = 0, phyCount = 0;
+ const char *enabledExts[10];
+ const char *enabledLayers[10];
+ uint32_t enabledExtsCount = 0, enabledLayersCount = 0, phyCount = 0;
vkh_layers_check_init();
- #ifdef VKVG_USE_VALIDATION
+#ifdef VKVG_USE_VALIDATION
if (vkh_layer_is_present("VK_LAYER_KHRONOS_validation"))
enabledLayers[enabledLayersCount++] = "VK_LAYER_KHRONOS_validation";
- #endif
+#endif
- #ifdef VKVG_USE_RENDERDOC
+#ifdef VKVG_USE_RENDERDOC
if (vkh_layer_is_present("VK_LAYER_RENDERDOC_Capture"))
enabledLayers[enabledLayersCount++] = "VK_LAYER_RENDERDOC_Capture";
- #endif
+#endif
vkh_layers_check_release();
- vkvg_get_required_instance_extensions (enabledExts, &enabledExtsCount);
+ vkvg_get_required_instance_extensions(enabledExts, &enabledExtsCount);
- #ifdef VK_VERSION_1_2
+#ifdef VK_VERSION_1_2
VkhApp app = vkh_app_create(1, 2, "vkvg", enabledLayersCount, enabledLayers, enabledExtsCount, enabledExts);
- #else
+#else
VkhApp app = vkh_app_create(1, 1, "vkvg", enabledLayersCount, enabledLayers, enabledExtsCount, enabledExts);
- #endif
+#endif
- #if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_app_enable_debug_messenger(app
- , VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
- , VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
- , NULL);
- #endif
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_app_enable_debug_messenger(app, VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, NULL);
+#endif
- VkhPhyInfo* phys = vkh_app_get_phyinfos (app, &phyCount, VK_NULL_HANDLE);
+ VkhPhyInfo *phys = vkh_app_get_phyinfos(app, &phyCount, VK_NULL_HANDLE);
if (phyCount == 0) {
dev->status = VKVG_STATUS_DEVICE_ERROR;
- vkh_app_destroy (app);
+ vkh_app_destroy(app);
return dev;
}
if (!(pi->properties.limits.framebufferColorSampleCounts & info->samples)) {
LOG(VKVG_LOG_ERR, "CREATE Device failed: sample count not supported: %d\n", info->samples);
dev->status = VKVG_STATUS_DEVICE_ERROR;
- vkh_app_free_phyinfos (phyCount, phys);
- vkh_app_destroy (app);
+ vkh_app_free_phyinfos(phyCount, phys);
+ vkh_app_destroy(app);
return dev;
}
- uint32_t qCount = 0;
- float qPriorities[] = {0.0};
- VkDeviceQueueCreateInfo pQueueInfos[] = { {0},{0},{0} };
+ uint32_t qCount = 0;
+ float qPriorities[] = {0.0};
+ VkDeviceQueueCreateInfo pQueueInfos[] = {{0}, {0}, {0}};
- if (vkh_phyinfo_create_queues (pi, pi->gQueue, 1, qPriorities, &pQueueInfos[qCount]))
+ if (vkh_phyinfo_create_queues(pi, pi->gQueue, 1, qPriorities, &pQueueInfos[qCount]))
qCount++;
- enabledExtsCount=0;
+ enabledExtsCount = 0;
- if (vkvg_get_required_device_extensions (pi->phy, enabledExts, &enabledExtsCount) != VKVG_STATUS_SUCCESS){
+ if (vkvg_get_required_device_extensions(pi->phy, enabledExts, &enabledExtsCount) != VKVG_STATUS_SUCCESS) {
dev->status = VKVG_STATUS_DEVICE_ERROR;
- vkh_app_free_phyinfos (phyCount, phys);
- vkh_app_destroy (app);
+ vkh_app_free_phyinfos(phyCount, phys);
+ vkh_app_destroy(app);
return dev;
}
VkPhysicalDeviceFeatures enabledFeatures = {0};
- const void* pNext = vkvg_get_device_requirements (&enabledFeatures);
-
- VkDeviceCreateInfo device_info = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- .queueCreateInfoCount = qCount,
- .pQueueCreateInfos = (VkDeviceQueueCreateInfo*)&pQueueInfos,
- .enabledExtensionCount = enabledExtsCount,
- .ppEnabledExtensionNames = enabledExts,
- .pEnabledFeatures = &enabledFeatures,
- .pNext = pNext};
- dev->vkhDev = vkh_device_create(app, pi, &device_info);
-
- vkh_app_free_phyinfos (phyCount, phys);
-
- info->inst = vkh_app_get_inst(app);
- info->phy = vkh_device_get_phy(dev->vkhDev);
- info->vkdev = vkh_device_get_vkdev(dev->vkhDev);
- info->qFamIdx = pi->gQueue;
- info->qIndex = 0;
+ const void *pNext = vkvg_get_device_requirements(&enabledFeatures);
+
+ VkDeviceCreateInfo device_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ .queueCreateInfoCount = qCount,
+ .pQueueCreateInfos = (VkDeviceQueueCreateInfo *)&pQueueInfos,
+ .enabledExtensionCount = enabledExtsCount,
+ .ppEnabledExtensionNames = enabledExts,
+ .pEnabledFeatures = &enabledFeatures,
+ .pNext = pNext};
+ dev->vkhDev = vkh_device_create(app, pi, &device_info);
+
+ vkh_app_free_phyinfos(phyCount, phys);
+
+ info->inst = vkh_app_get_inst(app);
+ info->phy = vkh_device_get_phy(dev->vkhDev);
+ info->vkdev = vkh_device_get_vkdev(dev->vkhDev);
+ info->qFamIdx = pi->gQueue;
+ info->qIndex = 0;
}
- _device_init (dev, info);
+ _device_init(dev, info);
- return dev;
+ return dev;
}
-void vkvg_device_destroy (VkvgDevice dev)
-{
- LOCK_DEVICE
- dev->references--;
- if (dev->references > 0) {
- UNLOCK_DEVICE
- return;
- }
- UNLOCK_DEVICE
-
-
- if (dev->cachedContextCount > 0) {
- _cached_ctx* cur = dev->cachedContextLast;
- while (cur) {
- _release_context_ressources (cur->ctx);
- _cached_ctx* prev = cur;
- cur = cur->pNext;
- free (prev);
- }
- }
-
+void vkvg_device_destroy(VkvgDevice dev) {
+ LOCK_DEVICE
+ dev->references--;
+ if (dev->references > 0) {
+ UNLOCK_DEVICE
+ return;
+ }
+ UNLOCK_DEVICE
+
+ if (dev->cachedContextCount > 0) {
+ _cached_ctx *cur = dev->cachedContextLast;
+ while (cur) {
+ _release_context_ressources(cur->ctx);
+ _cached_ctx *prev = cur;
+ cur = cur->pNext;
+ free(prev);
+ }
+ }
- LOG(VKVG_LOG_INFO, "DESTROY Device\n");
+ LOG(VKVG_LOG_INFO, "DESTROY Device\n");
- vkDeviceWaitIdle (dev->vkDev);
+ vkDeviceWaitIdle(dev->vkDev);
- vkh_image_destroy (dev->emptyImg);
+ vkh_image_destroy(dev->emptyImg);
- vkDestroyDescriptorSetLayout (dev->vkDev, dev->dslGrad,NULL);
- vkDestroyDescriptorSetLayout (dev->vkDev, dev->dslFont,NULL);
- vkDestroyDescriptorSetLayout (dev->vkDev, dev->dslSrc, NULL);
+ vkDestroyDescriptorSetLayout(dev->vkDev, dev->dslGrad, NULL);
+ vkDestroyDescriptorSetLayout(dev->vkDev, dev->dslFont, NULL);
+ vkDestroyDescriptorSetLayout(dev->vkDev, dev->dslSrc, NULL);
#ifndef __APPLE__
- vkDestroyPipeline (dev->vkDev, dev->pipelinePolyFill, NULL);
+ vkDestroyPipeline(dev->vkDev, dev->pipelinePolyFill, NULL);
#endif
- vkDestroyPipeline (dev->vkDev, dev->pipelineClipping, NULL);
+ vkDestroyPipeline(dev->vkDev, dev->pipelineClipping, NULL);
- vkDestroyPipeline (dev->vkDev, dev->pipe_OVER, NULL);
- vkDestroyPipeline (dev->vkDev, dev->pipe_SUB, NULL);
- vkDestroyPipeline (dev->vkDev, dev->pipe_CLEAR, NULL);
+ vkDestroyPipeline(dev->vkDev, dev->pipe_OVER, NULL);
+ vkDestroyPipeline(dev->vkDev, dev->pipe_SUB, NULL);
+ vkDestroyPipeline(dev->vkDev, dev->pipe_CLEAR, NULL);
#ifdef VKVG_WIRED_DEBUG
- vkDestroyPipeline (dev->vkDev, dev->pipelineWired, NULL);
- vkDestroyPipeline (dev->vkDev, dev->pipelineLineList, NULL);
+ vkDestroyPipeline(dev->vkDev, dev->pipelineWired, NULL);
+ vkDestroyPipeline(dev->vkDev, dev->pipelineLineList, NULL);
#endif
- vkDestroyPipelineLayout (dev->vkDev, dev->pipelineLayout, NULL);
- vkDestroyPipelineCache (dev->vkDev, dev->pipelineCache, NULL);
- vkDestroyRenderPass (dev->vkDev, dev->renderPass, NULL);
- vkDestroyRenderPass (dev->vkDev, dev->renderPass_ClearStencil, NULL);
- vkDestroyRenderPass (dev->vkDev, dev->renderPass_ClearAll, NULL);
+ vkDestroyPipelineLayout(dev->vkDev, dev->pipelineLayout, NULL);
+ vkDestroyPipelineCache(dev->vkDev, dev->pipelineCache, NULL);
+ vkDestroyRenderPass(dev->vkDev, dev->renderPass, NULL);
+ vkDestroyRenderPass(dev->vkDev, dev->renderPass_ClearStencil, NULL);
+ vkDestroyRenderPass(dev->vkDev, dev->renderPass_ClearAll, NULL);
- vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
- vkDestroyFence (dev->vkDev, dev->fence,NULL);
+ vkWaitForFences(dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
+ vkDestroyFence(dev->vkDev, dev->fence, NULL);
- vkFreeCommandBuffers (dev->vkDev, dev->cmdPool, 1, &dev->cmd);
- vkDestroyCommandPool (dev->vkDev, dev->cmdPool, NULL);
+ vkFreeCommandBuffers(dev->vkDev, dev->cmdPool, 1, &dev->cmd);
+ vkDestroyCommandPool(dev->vkDev, dev->cmdPool, NULL);
- vkh_queue_destroy(dev->gQueue);
+ vkh_queue_destroy(dev->gQueue);
- _font_cache_destroy(dev);
+ _font_cache_destroy(dev);
#ifdef VKH_USE_VMA
- vmaDestroyAllocator (dev->allocator);
+ vmaDestroyAllocator(dev->allocator);
#endif
- if (dev->threadAware)
- mtx_destroy (&dev->mutex);
+ if (dev->threadAware)
+ mtx_destroy(&dev->mutex);
- if (dev->vkhDev) {
- VkhApp app = vkh_device_get_app (dev->vkhDev);
- vkh_device_destroy (dev->vkhDev);
- vkh_app_destroy (app);
- }
+ if (dev->vkhDev) {
+ VkhApp app = vkh_device_get_app(dev->vkhDev);
+ vkh_device_destroy(dev->vkhDev);
+ vkh_app_destroy(app);
+ }
- free(dev);
+ free(dev);
}
-vkvg_status_t vkvg_device_status (VkvgDevice dev) {
- return dev->status;
-}
-VkvgDevice vkvg_device_reference (VkvgDevice dev) {
- LOCK_DEVICE
- dev->references++;
- UNLOCK_DEVICE
- return dev;
+vkvg_status_t vkvg_device_status(VkvgDevice dev) { return dev->status; }
+VkvgDevice vkvg_device_reference(VkvgDevice dev) {
+ LOCK_DEVICE
+ dev->references++;
+ UNLOCK_DEVICE
+ return dev;
}
-uint32_t vkvg_device_get_reference_count (VkvgDevice dev) {
- return dev->references;
-}
-void vkvg_device_set_dpy (VkvgDevice dev, int hdpy, int vdpy) {
- dev->hdpi = hdpy;
- dev->vdpi = vdpy;
+uint32_t vkvg_device_get_reference_count(VkvgDevice dev) { return dev->references; }
+void vkvg_device_set_dpy(VkvgDevice dev, int hdpy, int vdpy) {
+ dev->hdpi = hdpy;
+ dev->vdpi = vdpy;
- //TODO: reset font cache
+ // TODO: reset font cache
}
-void vkvg_device_get_dpy (VkvgDevice dev, int* hdpy, int* vdpy) {
- *hdpy = dev->hdpi;
- *vdpy = dev->vdpi;
+void vkvg_device_get_dpy(VkvgDevice dev, int *hdpy, int *vdpy) {
+ *hdpy = dev->hdpi;
+ *vdpy = dev->vdpi;
}
-void vkvg_device_set_thread_aware (VkvgDevice dev, uint32_t thread_aware) {
- if (thread_aware) {
- if (dev->threadAware)
- return;
- mtx_init (&dev->mutex, mtx_plain);
- mtx_init (&dev->fontCache->mutex, mtx_plain);
- dev->threadAware = true;
- } else if (dev->threadAware) {
- mtx_destroy (&dev->mutex);
- mtx_destroy (&dev->fontCache->mutex);
- dev->threadAware = false;
- }
+void vkvg_device_set_thread_aware(VkvgDevice dev, uint32_t thread_aware) {
+ if (thread_aware) {
+ if (dev->threadAware)
+ return;
+ mtx_init(&dev->mutex, mtx_plain);
+ mtx_init(&dev->fontCache->mutex, mtx_plain);
+ dev->threadAware = true;
+ } else if (dev->threadAware) {
+ mtx_destroy(&dev->mutex);
+ mtx_destroy(&dev->fontCache->mutex);
+ dev->threadAware = false;
+ }
}
#if VKVG_DBG_STATS
-vkvg_debug_stats_t vkvg_device_get_stats (VkvgDevice dev) {
- return dev->debug_stats;
-}
-vkvg_debug_stats_t vkvg_device_reset_stats (VkvgDevice dev) {
- dev->debug_stats = (vkvg_debug_stats_t) {0};
-}
+vkvg_debug_stats_t vkvg_device_get_stats(VkvgDevice dev) { return dev->debug_stats; }
+vkvg_debug_stats_t vkvg_device_reset_stats(VkvgDevice dev) { dev->debug_stats = (vkvg_debug_stats_t){0}; }
#endif
* THE SOFTWARE.
*/
-#define GetInstProcAddress(inst, func)(PFN_##func)vkGetInstanceProcAddr(inst, #func);
+#define GetInstProcAddress(inst, func) (PFN_##func) vkGetInstanceProcAddr(inst, #func);
-#define GetVkProcAddress(dev, inst, func)(vkGetDeviceProcAddr(dev,#func)==NULL)?(PFN_##func)vkGetInstanceProcAddr(inst, #func):(PFN_##func)vkGetDeviceProcAddr(dev, #func)
+#define GetVkProcAddress(dev, inst, func) \
+ (vkGetDeviceProcAddr(dev, #func) == NULL) ? (PFN_##func)vkGetInstanceProcAddr(inst, #func) \
+ : (PFN_##func)vkGetDeviceProcAddr(dev, #func)
#include "vkvg_device_internal.h"
#include "vkvg_context_internal.h"
vkvg_wired_debug_mode vkvg_wired_debug = vkvg_wired_debug_mode_normal;
#endif
-PFN_vkCmdBindPipeline CmdBindPipeline;
-PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
-PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer;
-PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers;
-
-PFN_vkCmdDrawIndexed CmdDrawIndexed;
-PFN_vkCmdDraw CmdDraw;
-
-PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask;
-PFN_vkCmdSetStencilReference CmdSetStencilReference;
-PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask;
-PFN_vkCmdBeginRenderPass CmdBeginRenderPass;
-PFN_vkCmdEndRenderPass CmdEndRenderPass;
-PFN_vkCmdSetViewport CmdSetViewport;
-PFN_vkCmdSetScissor CmdSetScissor;
-
-PFN_vkCmdPushConstants CmdPushConstants;
-
-PFN_vkWaitForFences WaitForFences;
-PFN_vkResetFences ResetFences;
-PFN_vkResetCommandBuffer ResetCommandBuffer;
-
-bool _device_try_get_phyinfo (VkhPhyInfo* phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo* phy) {
- for (uint32_t i=0; i<phyCount; i++){
- if (vkh_phyinfo_get_properties(phys[i]).deviceType == gpuType) {
- *phy = phys[i];
- return true;
- }
- }
- return false;
+PFN_vkCmdBindPipeline CmdBindPipeline;
+PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
+PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer;
+PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers;
+
+PFN_vkCmdDrawIndexed CmdDrawIndexed;
+PFN_vkCmdDraw CmdDraw;
+
+PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask;
+PFN_vkCmdSetStencilReference CmdSetStencilReference;
+PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask;
+PFN_vkCmdBeginRenderPass CmdBeginRenderPass;
+PFN_vkCmdEndRenderPass CmdEndRenderPass;
+PFN_vkCmdSetViewport CmdSetViewport;
+PFN_vkCmdSetScissor CmdSetScissor;
+
+PFN_vkCmdPushConstants CmdPushConstants;
+
+PFN_vkWaitForFences WaitForFences;
+PFN_vkResetFences ResetFences;
+PFN_vkResetCommandBuffer ResetCommandBuffer;
+
+bool _device_try_get_phyinfo(VkhPhyInfo *phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo *phy) {
+ for (uint32_t i = 0; i < phyCount; i++) {
+ if (vkh_phyinfo_get_properties(phys[i]).deviceType == gpuType) {
+ *phy = phys[i];
+ return true;
+ }
+ }
+ return false;
}
-//TODO:save/reload cache in user temp directory
-void _device_create_pipeline_cache(VkvgDevice dev){
+// TODO:save/reload cache in user temp directory
+void _device_create_pipeline_cache(VkvgDevice dev) {
- VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO};
- VK_CHECK_RESULT(vkCreatePipelineCache(dev->vkDev, &pipelineCacheCreateInfo, NULL, &dev->pipelineCache));
+ VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO};
+ VK_CHECK_RESULT(vkCreatePipelineCache(dev->vkDev, &pipelineCacheCreateInfo, NULL, &dev->pipelineCache));
}
-VkRenderPass _device_createRenderPassNoResolve(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp)
-{
- VkAttachmentDescription attColor = {
- .format = FB_COLOR_FORMAT,
- .samples = dev->samples,
- .loadOp = loadOp,
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
- .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
- .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
- .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
- VkAttachmentDescription attDS = {
- .format = dev->stencilFormat,
- .samples = dev->samples,
- .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
- .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
- .stencilLoadOp = stencilLoadOp,
- .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
- .initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
- .finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
-
- VkAttachmentDescription attachments[] = {attColor,attDS};
- VkAttachmentReference colorRef = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
- VkAttachmentReference dsRef = {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
-
- VkSubpassDescription subpassDescription = { .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
- .colorAttachmentCount = 1,
- .pColorAttachments = &colorRef,
- .pDepthStencilAttachment= &dsRef};
-
- VkSubpassDependency dependencies[] =
- {
- { VK_SUBPASS_EXTERNAL, 0,
- VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
- VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
- VK_DEPENDENCY_BY_REGION_BIT},
- { 0, VK_SUBPASS_EXTERNAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
- VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
- VK_DEPENDENCY_BY_REGION_BIT},
- };
-
- VkRenderPassCreateInfo renderPassInfo = { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
- .attachmentCount = 2,
- .pAttachments = attachments,
- .subpassCount = 1,
- .pSubpasses = &subpassDescription,
- .dependencyCount = 2,
- .pDependencies = dependencies
- };
- VkRenderPass rp;
- VK_CHECK_RESULT(vkCreateRenderPass(dev->vkDev, &renderPassInfo, NULL, &rp));
- return rp;
+VkRenderPass _device_createRenderPassNoResolve(VkvgDevice dev, VkAttachmentLoadOp loadOp,
+ VkAttachmentLoadOp stencilLoadOp) {
+ VkAttachmentDescription attColor = {.format = FB_COLOR_FORMAT,
+ .samples = dev->samples,
+ .loadOp = loadOp,
+ .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
+ VkAttachmentDescription attDS = {.format = dev->stencilFormat,
+ .samples = dev->samples,
+ .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ .stencilLoadOp = stencilLoadOp,
+ .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ .finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
+
+ VkAttachmentDescription attachments[] = {attColor, attDS};
+ VkAttachmentReference colorRef = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
+ VkAttachmentReference dsRef = {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
+
+ VkSubpassDescription subpassDescription = {.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
+ .colorAttachmentCount = 1,
+ .pColorAttachments = &colorRef,
+ .pDepthStencilAttachment = &dsRef};
+
+ VkSubpassDependency dependencies[] = {
+ {VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+ VK_DEPENDENCY_BY_REGION_BIT},
+ {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
+ VK_DEPENDENCY_BY_REGION_BIT},
+ };
+
+ VkRenderPassCreateInfo renderPassInfo = {.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ .attachmentCount = 2,
+ .pAttachments = attachments,
+ .subpassCount = 1,
+ .pSubpasses = &subpassDescription,
+ .dependencyCount = 2,
+ .pDependencies = dependencies};
+ VkRenderPass rp;
+ VK_CHECK_RESULT(vkCreateRenderPass(dev->vkDev, &renderPassInfo, NULL, &rp));
+ return rp;
}
-VkRenderPass _device_createRenderPassMS(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp)
-{
- VkAttachmentDescription attColor = {
- .format = FB_COLOR_FORMAT,
- .samples = dev->samples,
- .loadOp = loadOp,
- .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
- .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
- .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
- .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
- VkAttachmentDescription attColorResolve = {
- .format = FB_COLOR_FORMAT,
- .samples = VK_SAMPLE_COUNT_1_BIT,
- .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
- .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
- .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
- .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
- .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
- VkAttachmentDescription attDS = {
- .format = dev->stencilFormat,
- .samples = dev->samples,
- .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
- .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
- .stencilLoadOp = stencilLoadOp,
- .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
- .initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
- .finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
-
- VkAttachmentDescription attachments[] = {attColorResolve,attDS,attColor};
- VkAttachmentReference resolveRef= {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
- VkAttachmentReference dsRef = {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
- VkAttachmentReference colorRef = {2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
-
- VkSubpassDescription subpassDescription = { .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
- .colorAttachmentCount = 1,
- .pColorAttachments = &colorRef,
- .pResolveAttachments = &resolveRef,
- .pDepthStencilAttachment= &dsRef};
-
- VkSubpassDependency dependencies[] =
- {
- { VK_SUBPASS_EXTERNAL, 0,
- VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
- VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
- VK_DEPENDENCY_BY_REGION_BIT},
- { 0, VK_SUBPASS_EXTERNAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
- VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
- VK_DEPENDENCY_BY_REGION_BIT},
- };
-
- VkRenderPassCreateInfo renderPassInfo = { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
- .attachmentCount = 3,
- .pAttachments = attachments,
- .subpassCount = 1,
- .pSubpasses = &subpassDescription,
- .dependencyCount = 2,
- .pDependencies = dependencies
- };
- VkRenderPass rp;
- VK_CHECK_RESULT(vkCreateRenderPass(dev->vkDev, &renderPassInfo, NULL, &rp));
- return rp;
+VkRenderPass _device_createRenderPassMS(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp) {
+ VkAttachmentDescription attColor = {.format = FB_COLOR_FORMAT,
+ .samples = dev->samples,
+ .loadOp = loadOp,
+ .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
+ VkAttachmentDescription attColorResolve = {.format = FB_COLOR_FORMAT,
+ .samples = VK_SAMPLE_COUNT_1_BIT,
+ .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
+ VkAttachmentDescription attDS = {.format = dev->stencilFormat,
+ .samples = dev->samples,
+ .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ .stencilLoadOp = stencilLoadOp,
+ .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ .finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
+
+ VkAttachmentDescription attachments[] = {attColorResolve, attDS, attColor};
+ VkAttachmentReference resolveRef = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
+ VkAttachmentReference dsRef = {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
+ VkAttachmentReference colorRef = {2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
+
+ VkSubpassDescription subpassDescription = {.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
+ .colorAttachmentCount = 1,
+ .pColorAttachments = &colorRef,
+ .pResolveAttachments = &resolveRef,
+ .pDepthStencilAttachment = &dsRef};
+
+ VkSubpassDependency dependencies[] = {
+ {VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+ VK_DEPENDENCY_BY_REGION_BIT},
+ {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
+ VK_DEPENDENCY_BY_REGION_BIT},
+ };
+
+ VkRenderPassCreateInfo renderPassInfo = {.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ .attachmentCount = 3,
+ .pAttachments = attachments,
+ .subpassCount = 1,
+ .pSubpasses = &subpassDescription,
+ .dependencyCount = 2,
+ .pDependencies = dependencies};
+ VkRenderPass rp;
+ VK_CHECK_RESULT(vkCreateRenderPass(dev->vkDev, &renderPassInfo, NULL, &rp));
+ return rp;
}
-void _device_setupPipelines(VkvgDevice dev)
-{
- VkGraphicsPipelineCreateInfo pipelineCreateInfo = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
- .renderPass = dev->renderPass };
-
- VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
- .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN };
-
- VkPipelineRasterizationStateCreateInfo rasterizationState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
- .polygonMode = VK_POLYGON_MODE_FILL,
- .cullMode = VK_CULL_MODE_NONE,
- .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
- .depthClampEnable = VK_FALSE,
- .rasterizerDiscardEnable = VK_FALSE,
- .depthBiasEnable = VK_FALSE,
- .lineWidth = 1.0f };
-
- VkPipelineColorBlendAttachmentState blendAttachmentState =
- { .colorWriteMask = 0x0, .blendEnable = VK_TRUE,
+void _device_setupPipelines(VkvgDevice dev) {
+ VkGraphicsPipelineCreateInfo pipelineCreateInfo = {.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+ .renderPass = dev->renderPass};
+
+ VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+ .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN};
+
+ VkPipelineRasterizationStateCreateInfo rasterizationState = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
+ .polygonMode = VK_POLYGON_MODE_FILL,
+ .cullMode = VK_CULL_MODE_NONE,
+ .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
+ .depthClampEnable = VK_FALSE,
+ .rasterizerDiscardEnable = VK_FALSE,
+ .depthBiasEnable = VK_FALSE,
+ .lineWidth = 1.0f};
+
+ VkPipelineColorBlendAttachmentState blendAttachmentState = {
+ .colorWriteMask = 0x0,
+ .blendEnable = VK_TRUE,
#ifdef VKVG_PREMULT_ALPHA
- .srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
- .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
- .colorBlendOp = VK_BLEND_OP_ADD,
- .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
- .dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
- .alphaBlendOp = VK_BLEND_OP_ADD,
+ .srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
+ .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
+ .colorBlendOp = VK_BLEND_OP_ADD,
+ .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
+ .dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
+ .alphaBlendOp = VK_BLEND_OP_ADD,
#else
- .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA,
- .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
- .colorBlendOp = VK_BLEND_OP_ADD,
- .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
- .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
- .alphaBlendOp = VK_BLEND_OP_ADD,
+ .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA,
+ .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
+ .colorBlendOp = VK_BLEND_OP_ADD,
+ .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
+ .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
+ .alphaBlendOp = VK_BLEND_OP_ADD,
#endif
- };
-
- VkPipelineColorBlendStateCreateInfo colorBlendState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
- .attachmentCount = 1,
- .pAttachments = &blendAttachmentState };
-
- /*failOp,passOp,depthFailOp,compareOp, compareMask, writeMask, reference;*/
- VkStencilOpState polyFillOpState ={VK_STENCIL_OP_KEEP,VK_STENCIL_OP_INVERT, VK_STENCIL_OP_KEEP,VK_COMPARE_OP_EQUAL,STENCIL_CLIP_BIT,STENCIL_FILL_BIT,0};
- VkStencilOpState clipingOpState = {VK_STENCIL_OP_ZERO,VK_STENCIL_OP_REPLACE,VK_STENCIL_OP_KEEP,VK_COMPARE_OP_EQUAL,STENCIL_FILL_BIT,STENCIL_ALL_BIT, 0x2};
- VkStencilOpState stencilOpState = {VK_STENCIL_OP_KEEP,VK_STENCIL_OP_ZERO, VK_STENCIL_OP_KEEP,VK_COMPARE_OP_EQUAL,STENCIL_FILL_BIT,STENCIL_FILL_BIT,0x1};
-
- VkPipelineDepthStencilStateCreateInfo dsStateCreateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
- .depthTestEnable = VK_FALSE,
- .depthWriteEnable = VK_FALSE,
- .depthCompareOp = VK_COMPARE_OP_ALWAYS,
- .stencilTestEnable = VK_TRUE,
- .front = polyFillOpState,
- .back = polyFillOpState };
-
- VkDynamicState dynamicStateEnables[] = {
- VK_DYNAMIC_STATE_VIEWPORT,
- VK_DYNAMIC_STATE_SCISSOR,
- VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
- VK_DYNAMIC_STATE_STENCIL_REFERENCE,
- VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
- };
- VkPipelineDynamicStateCreateInfo dynamicState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
- .dynamicStateCount = 2,
- .pDynamicStates = dynamicStateEnables };
-
- VkPipelineViewportStateCreateInfo viewportState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
- .viewportCount = 1, .scissorCount = 1 };
-
- VkPipelineMultisampleStateCreateInfo multisampleState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
- .rasterizationSamples = dev->samples };
- /*if (dev->samples != VK_SAMPLE_COUNT_1_BIT){
- multisampleState.sampleShadingEnable = VK_TRUE;
- multisampleState.minSampleShading = 0.5f;
- }*/
- VkVertexInputBindingDescription vertexInputBinding = { .binding = 0,
- .stride = sizeof(Vertex),
- .inputRate = VK_VERTEX_INPUT_RATE_VERTEX };
-
- VkVertexInputAttributeDescription vertexInputAttributs[3] = {
- {0, 0, VK_FORMAT_R32G32_SFLOAT, 0},
- {1, 0, VK_FORMAT_R8G8B8A8_UNORM, 8},
- {2, 0, VK_FORMAT_R32G32B32_SFLOAT, 12}
- };
-
- VkPipelineVertexInputStateCreateInfo vertexInputState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
- .vertexBindingDescriptionCount = 1,
- .pVertexBindingDescriptions = &vertexInputBinding,
- .vertexAttributeDescriptionCount= 3,
- .pVertexAttributeDescriptions = vertexInputAttributs };
+ };
+
+ VkPipelineColorBlendStateCreateInfo colorBlendState = {.sType =
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+ .attachmentCount = 1,
+ .pAttachments = &blendAttachmentState};
+
+ /*failOp,passOp,depthFailOp,compareOp, compareMask, writeMask, reference;*/
+ VkStencilOpState polyFillOpState = {VK_STENCIL_OP_KEEP,
+ VK_STENCIL_OP_INVERT,
+ VK_STENCIL_OP_KEEP,
+ VK_COMPARE_OP_EQUAL,
+ STENCIL_CLIP_BIT,
+ STENCIL_FILL_BIT,
+ 0};
+ VkStencilOpState clipingOpState = {VK_STENCIL_OP_ZERO,
+ VK_STENCIL_OP_REPLACE,
+ VK_STENCIL_OP_KEEP,
+ VK_COMPARE_OP_EQUAL,
+ STENCIL_FILL_BIT,
+ STENCIL_ALL_BIT,
+ 0x2};
+ VkStencilOpState stencilOpState = {VK_STENCIL_OP_KEEP,
+ VK_STENCIL_OP_ZERO,
+ VK_STENCIL_OP_KEEP,
+ VK_COMPARE_OP_EQUAL,
+ STENCIL_FILL_BIT,
+ STENCIL_FILL_BIT,
+ 0x1};
+
+ VkPipelineDepthStencilStateCreateInfo dsStateCreateInfo = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
+ .depthTestEnable = VK_FALSE,
+ .depthWriteEnable = VK_FALSE,
+ .depthCompareOp = VK_COMPARE_OP_ALWAYS,
+ .stencilTestEnable = VK_TRUE,
+ .front = polyFillOpState,
+ .back = polyFillOpState};
+
+ VkDynamicState dynamicStateEnables[] = {
+ VK_DYNAMIC_STATE_VIEWPORT,
+ VK_DYNAMIC_STATE_SCISSOR,
+ VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
+ VK_DYNAMIC_STATE_STENCIL_REFERENCE,
+ VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
+ };
+ VkPipelineDynamicStateCreateInfo dynamicState = {.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
+ .dynamicStateCount = 2,
+ .pDynamicStates = dynamicStateEnables};
+
+ VkPipelineViewportStateCreateInfo viewportState = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, .viewportCount = 1, .scissorCount = 1};
+
+ VkPipelineMultisampleStateCreateInfo multisampleState = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, .rasterizationSamples = dev->samples};
+ /*if (dev->samples != VK_SAMPLE_COUNT_1_BIT){
+ multisampleState.sampleShadingEnable = VK_TRUE;
+ multisampleState.minSampleShading = 0.5f;
+ }*/
+ VkVertexInputBindingDescription vertexInputBinding = {
+ .binding = 0, .stride = sizeof(Vertex), .inputRate = VK_VERTEX_INPUT_RATE_VERTEX};
+
+ VkVertexInputAttributeDescription vertexInputAttributs[3] = {{0, 0, VK_FORMAT_R32G32_SFLOAT, 0},
+ {1, 0, VK_FORMAT_R8G8B8A8_UNORM, 8},
+ {2, 0, VK_FORMAT_R32G32B32_SFLOAT, 12}};
+
+ VkPipelineVertexInputStateCreateInfo vertexInputState = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ .vertexBindingDescriptionCount = 1,
+ .pVertexBindingDescriptions = &vertexInputBinding,
+ .vertexAttributeDescriptionCount = 3,
+ .pVertexAttributeDescriptions = vertexInputAttributs};
#ifdef VKVG_WIRED_DEBUG
- VkShaderModule modVert, modFrag, modFragWired;
+ VkShaderModule modVert, modFrag, modFragWired;
#else
- VkShaderModule modVert, modFrag;
+ VkShaderModule modVert, modFrag;
#endif
- VkShaderModuleCreateInfo createInfo = { .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
- .pCode = (uint32_t*)vkvg_main_vert_spv,
- .codeSize = vkvg_main_vert_spv_len };
- VK_CHECK_RESULT(vkCreateShaderModule(dev->vkDev, &createInfo, NULL, &modVert));
+ VkShaderModuleCreateInfo createInfo = {.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ .pCode = (uint32_t *)vkvg_main_vert_spv,
+ .codeSize = vkvg_main_vert_spv_len};
+ VK_CHECK_RESULT(vkCreateShaderModule(dev->vkDev, &createInfo, NULL, &modVert));
#if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
- createInfo.pCode = (uint32_t*)vkvg_main_lcd_frag_spv;
- createInfo.codeSize = vkvg_main_lcd_frag_spv_len;
+ createInfo.pCode = (uint32_t *)vkvg_main_lcd_frag_spv;
+ createInfo.codeSize = vkvg_main_lcd_frag_spv_len;
#else
- createInfo.pCode = (uint32_t*)vkvg_main_frag_spv;
- createInfo.codeSize = vkvg_main_frag_spv_len;
+ createInfo.pCode = (uint32_t *)vkvg_main_frag_spv;
+ createInfo.codeSize = vkvg_main_frag_spv_len;
#endif
- VK_CHECK_RESULT(vkCreateShaderModule(dev->vkDev, &createInfo, NULL, &modFrag));
-
- VkPipelineShaderStageCreateInfo vertStage = { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_VERTEX_BIT,
- .module = modVert,
- .pName = "main",
- };
- VkPipelineShaderStageCreateInfo fragStage = { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
- .module = modFrag,
- .pName = "main",
- };
-
- // Use specialization constants to pass number of samples to the shader (used for MSAA resolve)
- /*VkSpecializationMapEntry specializationEntry = {
- .constantID = 0,
- .offset = 0,
- .size = sizeof(uint32_t)};
- uint32_t specializationData = VKVG_SAMPLES;
- VkSpecializationInfo specializationInfo = {
- .mapEntryCount = 1,
- .pMapEntries = &specializationEntry,
- .dataSize = sizeof(specializationData),
- .pData = &specializationData};*/
-
- VkPipelineShaderStageCreateInfo shaderStages[] = {vertStage,fragStage};
-
- pipelineCreateInfo.stageCount = 1;
- pipelineCreateInfo.pStages = shaderStages;
- pipelineCreateInfo.pVertexInputState = &vertexInputState;
- pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
- pipelineCreateInfo.pViewportState = &viewportState;
- pipelineCreateInfo.pRasterizationState = &rasterizationState;
- pipelineCreateInfo.pMultisampleState = &multisampleState;
- pipelineCreateInfo.pColorBlendState = &colorBlendState;
- pipelineCreateInfo.pDepthStencilState = &dsStateCreateInfo;
- pipelineCreateInfo.pDynamicState = &dynamicState;
- pipelineCreateInfo.layout = dev->pipelineLayout;
+ VK_CHECK_RESULT(vkCreateShaderModule(dev->vkDev, &createInfo, NULL, &modFrag));
+
+ VkPipelineShaderStageCreateInfo vertStage = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = VK_SHADER_STAGE_VERTEX_BIT,
+ .module = modVert,
+ .pName = "main",
+ };
+ VkPipelineShaderStageCreateInfo fragStage = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
+ .module = modFrag,
+ .pName = "main",
+ };
+
+ // Use specialization constants to pass number of samples to the shader (used for MSAA resolve)
+ /*VkSpecializationMapEntry specializationEntry = {
+ .constantID = 0,
+ .offset = 0,
+ .size = sizeof(uint32_t)};
+ uint32_t specializationData = VKVG_SAMPLES;
+ VkSpecializationInfo specializationInfo = {
+ .mapEntryCount = 1,
+ .pMapEntries = &specializationEntry,
+ .dataSize = sizeof(specializationData),
+ .pData = &specializationData};*/
+
+ VkPipelineShaderStageCreateInfo shaderStages[] = {vertStage, fragStage};
+
+ pipelineCreateInfo.stageCount = 1;
+ pipelineCreateInfo.pStages = shaderStages;
+ pipelineCreateInfo.pVertexInputState = &vertexInputState;
+ pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
+ pipelineCreateInfo.pViewportState = &viewportState;
+ pipelineCreateInfo.pRasterizationState = &rasterizationState;
+ pipelineCreateInfo.pMultisampleState = &multisampleState;
+ pipelineCreateInfo.pColorBlendState = &colorBlendState;
+ pipelineCreateInfo.pDepthStencilState = &dsStateCreateInfo;
+ pipelineCreateInfo.pDynamicState = &dynamicState;
+ pipelineCreateInfo.layout = dev->pipelineLayout;
#ifndef __APPLE__
- VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipelinePolyFill));
+ VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL,
+ &dev->pipelinePolyFill));
#endif
- inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
- dsStateCreateInfo.back = dsStateCreateInfo.front = clipingOpState;
- dynamicState.dynamicStateCount = 5;
- VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipelineClipping));
-
- dsStateCreateInfo.back = dsStateCreateInfo.front = stencilOpState;
- blendAttachmentState.colorWriteMask=0xf;
- dynamicState.dynamicStateCount = 3;
- pipelineCreateInfo.stageCount = 2;
- VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipe_OVER));
-
- blendAttachmentState.alphaBlendOp = blendAttachmentState.colorBlendOp = VK_BLEND_OP_SUBTRACT;
- VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipe_SUB));
-
- colorBlendState.logicOpEnable = VK_TRUE;
- blendAttachmentState.blendEnable = VK_FALSE;
- colorBlendState.logicOp = VK_LOGIC_OP_CLEAR;
- VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipe_CLEAR));
-
+ inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ dsStateCreateInfo.back = dsStateCreateInfo.front = clipingOpState;
+ dynamicState.dynamicStateCount = 5;
+ VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL,
+ &dev->pipelineClipping));
+
+ dsStateCreateInfo.back = dsStateCreateInfo.front = stencilOpState;
+ blendAttachmentState.colorWriteMask = 0xf;
+ dynamicState.dynamicStateCount = 3;
+ pipelineCreateInfo.stageCount = 2;
+ VK_CHECK_RESULT(
+ vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipe_OVER));
+
+ blendAttachmentState.alphaBlendOp = blendAttachmentState.colorBlendOp = VK_BLEND_OP_SUBTRACT;
+ VK_CHECK_RESULT(
+ vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipe_SUB));
+
+ colorBlendState.logicOpEnable = VK_TRUE;
+ blendAttachmentState.blendEnable = VK_FALSE;
+ colorBlendState.logicOp = VK_LOGIC_OP_CLEAR;
+ VK_CHECK_RESULT(
+ vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipe_CLEAR));
#ifdef VKVG_WIRED_DEBUG
- colorBlendState.logicOpEnable = VK_FALSE;
- blendAttachmentState.blendEnable = VK_TRUE;
- colorBlendState.logicOp = VK_LOGIC_OP_CLEAR;
+ colorBlendState.logicOpEnable = VK_FALSE;
+ blendAttachmentState.blendEnable = VK_TRUE;
+ colorBlendState.logicOp = VK_LOGIC_OP_CLEAR;
- createInfo.pCode = (uint32_t*)wired_frag_spv;
+ createInfo.pCode = (uint32_t *)wired_frag_spv;
- createInfo.codeSize = wired_frag_spv_len;
- VK_CHECK_RESULT(vkCreateShaderModule(dev->vkDev, &createInfo, NULL, &modFragWired));
+ createInfo.codeSize = wired_frag_spv_len;
+ VK_CHECK_RESULT(vkCreateShaderModule(dev->vkDev, &createInfo, NULL, &modFragWired));
- shaderStages[1].module = modFragWired;
+ shaderStages[1].module = modFragWired;
- rasterizationState.polygonMode = VK_POLYGON_MODE_LINE;
- VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipelineLineList));
+ rasterizationState.polygonMode = VK_POLYGON_MODE_LINE;
+ VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL,
+ &dev->pipelineLineList));
- inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
- rasterizationState.polygonMode = VK_POLYGON_MODE_FILL;
- VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipelineWired));
+ inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
+ rasterizationState.polygonMode = VK_POLYGON_MODE_FILL;
+ VK_CHECK_RESULT(
+ vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipelineWired));
- vkDestroyShaderModule(dev->vkDev, modFragWired, NULL);
+ vkDestroyShaderModule(dev->vkDev, modFragWired, NULL);
#endif
- vkDestroyShaderModule(dev->vkDev, modVert, NULL);
- vkDestroyShaderModule(dev->vkDev, modFrag, NULL);
+ vkDestroyShaderModule(dev->vkDev, modVert, NULL);
+ vkDestroyShaderModule(dev->vkDev, modFrag, NULL);
}
-void _device_createDescriptorSetLayout (VkvgDevice dev) {
-
- VkDescriptorSetLayoutBinding dsLayoutBinding =
- {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1,VK_SHADER_STAGE_FRAGMENT_BIT, NULL};
- VkDescriptorSetLayoutCreateInfo dsLayoutCreateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .bindingCount = 1,
- .pBindings = &dsLayoutBinding };
- VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslFont));
- VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslSrc));
- dsLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslGrad));
-
- VkPushConstantRange pushConstantRange[] = {
- {VK_SHADER_STAGE_VERTEX_BIT,0,sizeof(push_constants)},
- //{VK_SHADER_STAGE_FRAGMENT_BIT,0,sizeof(push_constants)}
- };
- VkDescriptorSetLayout dsls[] = {dev->dslFont,dev->dslSrc,dev->dslGrad};
-
- VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .pushConstantRangeCount = 1,
- .pPushConstantRanges = (VkPushConstantRange*)&pushConstantRange,
- .setLayoutCount = 3,
- .pSetLayouts = dsls };
- VK_CHECK_RESULT(vkCreatePipelineLayout(dev->vkDev, &pipelineLayoutCreateInfo, NULL, &dev->pipelineLayout));
+void _device_createDescriptorSetLayout(VkvgDevice dev) {
+
+ VkDescriptorSetLayoutBinding dsLayoutBinding = {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1,
+ VK_SHADER_STAGE_FRAGMENT_BIT, NULL};
+ VkDescriptorSetLayoutCreateInfo dsLayoutCreateInfo = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, .bindingCount = 1, .pBindings = &dsLayoutBinding};
+ VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslFont));
+ VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslSrc));
+ dsLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslGrad));
+
+ VkPushConstantRange pushConstantRange[] = {
+ {VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(push_constants)},
+ //{VK_SHADER_STAGE_FRAGMENT_BIT,0,sizeof(push_constants)}
+ };
+ VkDescriptorSetLayout dsls[] = {dev->dslFont, dev->dslSrc, dev->dslGrad};
+
+ VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ .pushConstantRangeCount = 1,
+ .pPushConstantRanges =
+ (VkPushConstantRange *)&pushConstantRange,
+ .setLayoutCount = 3,
+ .pSetLayouts = dsls};
+ VK_CHECK_RESULT(vkCreatePipelineLayout(dev->vkDev, &pipelineLayoutCreateInfo, NULL, &dev->pipelineLayout));
}
-void _device_wait_idle (VkvgDevice dev) {
- vkDeviceWaitIdle (dev->vkDev);
-}
-void _device_wait_and_reset_device_fence (VkvgDevice dev) {
- vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
- ResetFences (dev->vkDev, 1, &dev->fence);
+void _device_wait_idle(VkvgDevice dev) { vkDeviceWaitIdle(dev->vkDev); }
+void _device_wait_and_reset_device_fence(VkvgDevice dev) {
+ vkWaitForFences(dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
+ ResetFences(dev->vkDev, 1, &dev->fence);
}
-bool _device_try_get_cached_context (VkvgDevice dev, VkvgContext* pCtx) {
- LOCK_DEVICE
-
- if (dev->cachedContextCount) {
- thrd_t curThread = thrd_current ();
- _cached_ctx* prev = NULL;
- _cached_ctx* cur = dev->cachedContextLast;
- while (cur) {
- if (thrd_equal (cur->thread, curThread)) {
- if (prev)
- prev->pNext = cur->pNext;
- else
- dev->cachedContextLast = cur->pNext;
-
- dev->cachedContextCount--;
-
- LOG(VKVG_LOG_THREAD,"get cached context: %p, thd:%lu cached ctx: %d\n", cur->ctx, cur->thread, dev->cachedContextCount);
-
- *pCtx = cur->ctx;
- free (cur);
- UNLOCK_DEVICE
- return true;
- }
- prev = cur;
- cur = cur->pNext;
- }
- }
- *pCtx = NULL;
- UNLOCK_DEVICE
- return false;
+bool _device_try_get_cached_context(VkvgDevice dev, VkvgContext *pCtx) {
+ LOCK_DEVICE
+
+ if (dev->cachedContextCount) {
+ thrd_t curThread = thrd_current();
+ _cached_ctx *prev = NULL;
+ _cached_ctx *cur = dev->cachedContextLast;
+ while (cur) {
+ if (thrd_equal(cur->thread, curThread)) {
+ if (prev)
+ prev->pNext = cur->pNext;
+ else
+ dev->cachedContextLast = cur->pNext;
+
+ dev->cachedContextCount--;
+
+ LOG(VKVG_LOG_THREAD, "get cached context: %p, thd:%lu cached ctx: %d\n", cur->ctx, cur->thread,
+ dev->cachedContextCount);
+
+ *pCtx = cur->ctx;
+ free(cur);
+ UNLOCK_DEVICE
+ return true;
+ }
+ prev = cur;
+ cur = cur->pNext;
+ }
+ }
+ *pCtx = NULL;
+ UNLOCK_DEVICE
+ return false;
}
-void _device_store_context (VkvgContext ctx) {
- VkvgDevice dev = ctx->dev;
+void _device_store_context(VkvgContext ctx) {
+ VkvgDevice dev = ctx->dev;
- LOCK_DEVICE
+ LOCK_DEVICE
- _cached_ctx* cur = (_cached_ctx*)calloc(1, sizeof(_cached_ctx));
- cur->ctx = ctx;
- cur->thread = thrd_current ();
- cur->pNext = dev->cachedContextLast;
+ _cached_ctx *cur = (_cached_ctx *)calloc(1, sizeof(_cached_ctx));
+ cur->ctx = ctx;
+ cur->thread = thrd_current();
+ cur->pNext = dev->cachedContextLast;
- dev->cachedContextLast = cur;
- dev->cachedContextCount++;
+ dev->cachedContextLast = cur;
+ dev->cachedContextCount++;
- LOG(VKVG_LOG_THREAD,"store context: %p, thd:%lu cached ctx: %d\n", cur->ctx, cur->thread, dev->cachedContextCount);
+ LOG(VKVG_LOG_THREAD, "store context: %p, thd:%lu cached ctx: %d\n", cur->ctx, cur->thread, dev->cachedContextCount);
- ctx->references++;
+ ctx->references++;
- UNLOCK_DEVICE
+ UNLOCK_DEVICE
}
-void _device_submit_cmd (VkvgDevice dev, VkCommandBuffer* cmd, VkFence fence) {
- LOCK_DEVICE
- vkh_cmd_submit (dev->gQueue, cmd, fence);
- UNLOCK_DEVICE
+void _device_submit_cmd(VkvgDevice dev, VkCommandBuffer *cmd, VkFence fence) {
+ LOCK_DEVICE
+ vkh_cmd_submit(dev->gQueue, cmd, fence);
+ UNLOCK_DEVICE
}
-bool _device_init_function_pointers (VkvgDevice dev) {
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- if (vkGetInstanceProcAddr(dev->instance, "vkSetDebugUtilsObjectNameEXT")==VK_NULL_HANDLE){
- LOG(VKVG_LOG_ERR, "vkvg create device failed: 'VK_EXT_debug_utils' has to be loaded for Debug build\n");
- return false;
- }
- vkh_device_init_debug_utils ((VkhDevice)dev);
+bool _device_init_function_pointers(VkvgDevice dev) {
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ if (vkGetInstanceProcAddr(dev->instance, "vkSetDebugUtilsObjectNameEXT") == VK_NULL_HANDLE) {
+ LOG(VKVG_LOG_ERR, "vkvg create device failed: 'VK_EXT_debug_utils' has to be loaded for Debug build\n");
+ return false;
+ }
+ vkh_device_init_debug_utils((VkhDevice)dev);
#endif
- CmdBindPipeline = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBindPipeline);
- CmdBindDescriptorSets = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBindDescriptorSets);
- CmdBindIndexBuffer = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBindIndexBuffer);
- CmdBindVertexBuffers = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBindVertexBuffers);
- CmdDrawIndexed = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdDrawIndexed);
- CmdDraw = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdDraw);
- CmdSetStencilCompareMask= GetVkProcAddress(dev->vkDev, dev->instance, vkCmdSetStencilCompareMask);
- CmdSetStencilReference = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdSetStencilReference);
- CmdSetStencilWriteMask = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdSetStencilWriteMask);
- CmdBeginRenderPass = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBeginRenderPass);
- CmdEndRenderPass = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdEndRenderPass);
- CmdSetViewport = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdSetViewport);
- CmdSetScissor = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdSetScissor);
- CmdPushConstants = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdPushConstants);
- WaitForFences = GetVkProcAddress(dev->vkDev, dev->instance, vkWaitForFences);
- ResetFences = GetVkProcAddress(dev->vkDev, dev->instance, vkResetFences);
- ResetCommandBuffer = GetVkProcAddress(dev->vkDev, dev->instance, vkResetCommandBuffer);
- return true;
+ CmdBindPipeline = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBindPipeline);
+ CmdBindDescriptorSets = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBindDescriptorSets);
+ CmdBindIndexBuffer = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBindIndexBuffer);
+ CmdBindVertexBuffers = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBindVertexBuffers);
+ CmdDrawIndexed = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdDrawIndexed);
+ CmdDraw = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdDraw);
+ CmdSetStencilCompareMask = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdSetStencilCompareMask);
+ CmdSetStencilReference = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdSetStencilReference);
+ CmdSetStencilWriteMask = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdSetStencilWriteMask);
+ CmdBeginRenderPass = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBeginRenderPass);
+ CmdEndRenderPass = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdEndRenderPass);
+ CmdSetViewport = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdSetViewport);
+ CmdSetScissor = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdSetScissor);
+ CmdPushConstants = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdPushConstants);
+ WaitForFences = GetVkProcAddress(dev->vkDev, dev->instance, vkWaitForFences);
+ ResetFences = GetVkProcAddress(dev->vkDev, dev->instance, vkResetFences);
+ ResetCommandBuffer = GetVkProcAddress(dev->vkDev, dev->instance, vkResetCommandBuffer);
+ return true;
}
-void _device_create_empty_texture (VkvgDevice dev, VkFormat format, VkImageTiling tiling) {
- //create empty image to bind to context source descriptor when not in use
- dev->emptyImg = vkh_image_create((VkhDevice)dev,format,16,16,tiling,VKH_MEMORY_USAGE_GPU_ONLY,
- VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
- vkh_image_create_descriptor(dev->emptyImg, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
-
- _device_wait_and_reset_device_fence (dev);
-
- vkh_cmd_begin (dev->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- vkh_image_set_layout (dev->cmd, dev->emptyImg, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
- vkh_cmd_end (dev->cmd);
- _device_submit_cmd (dev, &dev->cmd, dev->fence);
+void _device_create_empty_texture(VkvgDevice dev, VkFormat format, VkImageTiling tiling) {
+ // create empty image to bind to context source descriptor when not in use
+ dev->emptyImg = vkh_image_create((VkhDevice)dev, format, 16, 16, tiling, VKH_MEMORY_USAGE_GPU_ONLY,
+ VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
+ vkh_image_create_descriptor(dev->emptyImg, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST,
+ VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
+
+ _device_wait_and_reset_device_fence(dev);
+
+ vkh_cmd_begin(dev->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ vkh_image_set_layout(dev->cmd, dev->emptyImg, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
+ vkh_cmd_end(dev->cmd);
+ _device_submit_cmd(dev, &dev->cmd, dev->fence);
}
-void _device_check_best_image_tiling (VkvgDevice dev, VkFormat format) {
- VkFlags stencilFormats[] = { VK_FORMAT_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT };
- VkFormatProperties phyStencilProps = { 0 }, phyImgProps = { 0 };
-
- //check png blit format
- VkFlags pngBlitFormats[] = { VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_R8G8B8A8_UNORM};
- dev->pngStagFormat = VK_FORMAT_UNDEFINED;
- for (int i = 0; i < 2; i++)
- {
- vkGetPhysicalDeviceFormatProperties(dev->phy, pngBlitFormats[i], &phyImgProps);
- if ((phyImgProps.linearTilingFeatures & VKVG_PNG_WRITE_IMG_REQUIREMENTS) == VKVG_PNG_WRITE_IMG_REQUIREMENTS) {
- dev->pngStagFormat = pngBlitFormats[i];
- dev->pngStagTiling = VK_IMAGE_TILING_LINEAR;
- break;
- } else if ((phyImgProps.optimalTilingFeatures & VKVG_PNG_WRITE_IMG_REQUIREMENTS) == VKVG_PNG_WRITE_IMG_REQUIREMENTS) {
- dev->pngStagFormat = pngBlitFormats[i];
- dev->pngStagTiling = VK_IMAGE_TILING_OPTIMAL;
- break;
- }
- }
-
- if (dev->pngStagFormat == VK_FORMAT_UNDEFINED)
- LOG(VKVG_LOG_DEBUG, "vkvg create device failed: no suitable image format for png write\n");
-
- dev->stencilFormat = VK_FORMAT_UNDEFINED;
- dev->stencilAspectFlag = VK_IMAGE_ASPECT_STENCIL_BIT;
- dev->supportedTiling = 0xff;
-
- vkGetPhysicalDeviceFormatProperties(dev->phy, format, &phyImgProps);
-
- if ((phyImgProps.optimalTilingFeatures & VKVG_SURFACE_IMGS_REQUIREMENTS) == VKVG_SURFACE_IMGS_REQUIREMENTS) {
- for (int i = 0; i < 4; i++)
- {
- vkGetPhysicalDeviceFormatProperties(dev->phy, stencilFormats[i], &phyStencilProps);
- if (phyStencilProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
- dev->stencilFormat = stencilFormats[i];
- if (i > 0)
- dev->stencilAspectFlag |= VK_IMAGE_ASPECT_DEPTH_BIT;
- dev->supportedTiling = VK_IMAGE_TILING_OPTIMAL;
- return;
- }
- }
- }
- if ((phyImgProps.linearTilingFeatures & VKVG_SURFACE_IMGS_REQUIREMENTS) == VKVG_SURFACE_IMGS_REQUIREMENTS) {
- for (int i = 0; i < 4; i++)
- {
- vkGetPhysicalDeviceFormatProperties(dev->phy, stencilFormats[i], &phyStencilProps);
- if (phyStencilProps.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
- dev->stencilFormat = stencilFormats[i];
- if (i > 0)
- dev->stencilAspectFlag |= VK_IMAGE_ASPECT_DEPTH_BIT;
- dev->supportedTiling = VK_IMAGE_TILING_LINEAR;
- return;
- }
- }
- }
- dev->status = VKVG_STATUS_INVALID_FORMAT;
- LOG(VKVG_LOG_ERR, "vkvg create device failed: image format not supported: %d\n", format);
+void _device_check_best_image_tiling(VkvgDevice dev, VkFormat format) {
+ VkFlags stencilFormats[] = {VK_FORMAT_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT,
+ VK_FORMAT_D32_SFLOAT_S8_UINT};
+ VkFormatProperties phyStencilProps = {0}, phyImgProps = {0};
+
+ // check png blit format
+ VkFlags pngBlitFormats[] = {VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_R8G8B8A8_UNORM};
+ dev->pngStagFormat = VK_FORMAT_UNDEFINED;
+ for (int i = 0; i < 2; i++) {
+ vkGetPhysicalDeviceFormatProperties(dev->phy, pngBlitFormats[i], &phyImgProps);
+ if ((phyImgProps.linearTilingFeatures & VKVG_PNG_WRITE_IMG_REQUIREMENTS) == VKVG_PNG_WRITE_IMG_REQUIREMENTS) {
+ dev->pngStagFormat = pngBlitFormats[i];
+ dev->pngStagTiling = VK_IMAGE_TILING_LINEAR;
+ break;
+ } else if ((phyImgProps.optimalTilingFeatures & VKVG_PNG_WRITE_IMG_REQUIREMENTS) ==
+ VKVG_PNG_WRITE_IMG_REQUIREMENTS) {
+ dev->pngStagFormat = pngBlitFormats[i];
+ dev->pngStagTiling = VK_IMAGE_TILING_OPTIMAL;
+ break;
+ }
+ }
+
+ if (dev->pngStagFormat == VK_FORMAT_UNDEFINED)
+ LOG(VKVG_LOG_DEBUG, "vkvg create device failed: no suitable image format for png write\n");
+
+ dev->stencilFormat = VK_FORMAT_UNDEFINED;
+ dev->stencilAspectFlag = VK_IMAGE_ASPECT_STENCIL_BIT;
+ dev->supportedTiling = 0xff;
+
+ vkGetPhysicalDeviceFormatProperties(dev->phy, format, &phyImgProps);
+
+ if ((phyImgProps.optimalTilingFeatures & VKVG_SURFACE_IMGS_REQUIREMENTS) == VKVG_SURFACE_IMGS_REQUIREMENTS) {
+ for (int i = 0; i < 4; i++) {
+ vkGetPhysicalDeviceFormatProperties(dev->phy, stencilFormats[i], &phyStencilProps);
+ if (phyStencilProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ dev->stencilFormat = stencilFormats[i];
+ if (i > 0)
+ dev->stencilAspectFlag |= VK_IMAGE_ASPECT_DEPTH_BIT;
+ dev->supportedTiling = VK_IMAGE_TILING_OPTIMAL;
+ return;
+ }
+ }
+ }
+ if ((phyImgProps.linearTilingFeatures & VKVG_SURFACE_IMGS_REQUIREMENTS) == VKVG_SURFACE_IMGS_REQUIREMENTS) {
+ for (int i = 0; i < 4; i++) {
+ vkGetPhysicalDeviceFormatProperties(dev->phy, stencilFormats[i], &phyStencilProps);
+ if (phyStencilProps.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ dev->stencilFormat = stencilFormats[i];
+ if (i > 0)
+ dev->stencilAspectFlag |= VK_IMAGE_ASPECT_DEPTH_BIT;
+ dev->supportedTiling = VK_IMAGE_TILING_LINEAR;
+ return;
+ }
+ }
+ }
+ dev->status = VKVG_STATUS_INVALID_FORMAT;
+ LOG(VKVG_LOG_ERR, "vkvg create device failed: image format not supported: %d\n", format);
}
-void _dump_image_format_properties (VkvgDevice dev, VkFormat format) {
- /*VkImageFormatProperties imgProps;
- VK_CHECK_RESULT(vkGetPhysicalDeviceImageFormatProperties(dev->phy,
- format, VK_IMAGE_TYPE_2D, VKVG_TILING,
- VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT,
- 0, &imgProps));
- printf ("tiling = %d\n", VKVG_TILING);
- printf ("max extend = (%d, %d, %d)\n", imgProps.maxExtent.width, imgProps.maxExtent.height, imgProps.maxExtent.depth);
- printf ("max mip levels = %d\n", imgProps.maxMipLevels);
- printf ("max array layers = %d\n", imgProps.maxArrayLayers);
- printf ("sample counts = ");
- if (imgProps.sampleCounts & VK_SAMPLE_COUNT_1_BIT)
- printf ("1,");
- if (imgProps.sampleCounts & VK_SAMPLE_COUNT_2_BIT)
- printf ("2,");
- if (imgProps.sampleCounts & VK_SAMPLE_COUNT_4_BIT)
- printf ("4,");
- if (imgProps.sampleCounts & VK_SAMPLE_COUNT_8_BIT)
- printf ("8,");
- if (imgProps.sampleCounts & VK_SAMPLE_COUNT_16_BIT)
- printf ("16,");
- if (imgProps.sampleCounts & VK_SAMPLE_COUNT_32_BIT)
- printf ("32,");
- printf ("\n");
- printf ("max resource size= %lu\n", imgProps.maxResourceSize);
+void _dump_image_format_properties(VkvgDevice dev, VkFormat format) {
+ /*VkImageFormatProperties imgProps;
+ VK_CHECK_RESULT(vkGetPhysicalDeviceImageFormatProperties(dev->phy,
+ format, VK_IMAGE_TYPE_2D, VKVG_TILING,
+ VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+ 0, &imgProps));
+ printf ("tiling = %d\n", VKVG_TILING);
+ printf ("max extend = (%d, %d, %d)\n", imgProps.maxExtent.width, imgProps.maxExtent.height,
+ imgProps.maxExtent.depth); printf ("max mip levels = %d\n", imgProps.maxMipLevels); printf ("max array layers =
+ %d\n", imgProps.maxArrayLayers); printf ("sample counts = "); if (imgProps.sampleCounts & VK_SAMPLE_COUNT_1_BIT)
+ printf ("1,");
+ if (imgProps.sampleCounts & VK_SAMPLE_COUNT_2_BIT)
+ printf ("2,");
+ if (imgProps.sampleCounts & VK_SAMPLE_COUNT_4_BIT)
+ printf ("4,");
+ if (imgProps.sampleCounts & VK_SAMPLE_COUNT_8_BIT)
+ printf ("8,");
+ if (imgProps.sampleCounts & VK_SAMPLE_COUNT_16_BIT)
+ printf ("16,");
+ if (imgProps.sampleCounts & VK_SAMPLE_COUNT_32_BIT)
+ printf ("32,");
+ printf ("\n");
+ printf ("max resource size= %lu\n", imgProps.maxResourceSize);
*/
-
}
#include "vkvg_internal.h"
#include "vkvg_fonts.h"
-#define STENCIL_FILL_BIT 0x1
-#define STENCIL_CLIP_BIT 0x2
-#define STENCIL_ALL_BIT 0x3
+#define STENCIL_FILL_BIT 0x1
+#define STENCIL_CLIP_BIT 0x2
+#define STENCIL_ALL_BIT 0x3
#define VKVG_MAX_CACHED_CONTEXT_COUNT 2
-extern PFN_vkCmdBindPipeline CmdBindPipeline;
-extern PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
-extern PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer;
-extern PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers;
-
-extern PFN_vkCmdDrawIndexed CmdDrawIndexed;
-extern PFN_vkCmdDraw CmdDraw;
-
-extern PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask;
-extern PFN_vkCmdSetStencilReference CmdSetStencilReference;
-extern PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask;
-extern PFN_vkCmdBeginRenderPass CmdBeginRenderPass;
-extern PFN_vkCmdEndRenderPass CmdEndRenderPass;
-extern PFN_vkCmdSetViewport CmdSetViewport;
-extern PFN_vkCmdSetScissor CmdSetScissor;
-
-extern PFN_vkCmdPushConstants CmdPushConstants;
-extern PFN_vkWaitForFences WaitForFences;
-extern PFN_vkResetFences ResetFences;
-extern PFN_vkResetCommandBuffer ResetCommandBuffer;
-
-typedef struct _cached_ctx{
- thrd_t thread;
- VkvgContext ctx;
- struct _cached_ctx* pNext;
+extern PFN_vkCmdBindPipeline CmdBindPipeline;
+extern PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
+extern PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer;
+extern PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers;
+
+extern PFN_vkCmdDrawIndexed CmdDrawIndexed;
+extern PFN_vkCmdDraw CmdDraw;
+
+extern PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask;
+extern PFN_vkCmdSetStencilReference CmdSetStencilReference;
+extern PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask;
+extern PFN_vkCmdBeginRenderPass CmdBeginRenderPass;
+extern PFN_vkCmdEndRenderPass CmdEndRenderPass;
+extern PFN_vkCmdSetViewport CmdSetViewport;
+extern PFN_vkCmdSetScissor CmdSetScissor;
+
+extern PFN_vkCmdPushConstants CmdPushConstants;
+extern PFN_vkWaitForFences WaitForFences;
+extern PFN_vkResetFences ResetFences;
+extern PFN_vkResetCommandBuffer ResetCommandBuffer;
+
+typedef struct _cached_ctx {
+ thrd_t thread;
+ VkvgContext ctx;
+ struct _cached_ctx *pNext;
} _cached_ctx;
typedef struct _vkvg_device_t {
- VkDevice vkDev; /**< Vulkan Logical Device */
- VkPhysicalDeviceMemoryProperties phyMemProps; /**< Vulkan Physical device memory properties */
- VkPhysicalDevice phy; /**< Vulkan Physical device */
- VkInstance instance; /**< Vulkan instance */
+ VkDevice vkDev; /**< Vulkan Logical Device */
+ VkPhysicalDeviceMemoryProperties phyMemProps; /**< Vulkan Physical device memory properties */
+ VkPhysicalDevice phy; /**< Vulkan Physical device */
+ VkInstance instance; /**< Vulkan instance */
#ifdef VKH_USE_VMA
- void* allocator; /**< Vulkan Memory allocator */
+ void *allocator; /**< Vulkan Memory allocator */
#endif
- VkImageTiling supportedTiling; /**< Supported image tiling for surface, 0xFF=no support */
- VkFormat stencilFormat; /**< Supported vulkan image format for stencil */
- VkImageAspectFlags stencilAspectFlag; /**< stencil only or depth stencil, could be solved by VK_KHR_separate_depth_stencil_layouts*/
- VkFormat pngStagFormat; /**< Supported vulkan image format png write staging img */
- VkImageTiling pngStagTiling; /**< tiling for the blit operation */
+ VkImageTiling supportedTiling; /**< Supported image tiling for surface, 0xFF=no support */
+ VkFormat stencilFormat; /**< Supported vulkan image format for stencil */
+ VkImageAspectFlags stencilAspectFlag; /**< stencil only or depth stencil, could be solved by
+ VK_KHR_separate_depth_stencil_layouts*/
+ VkFormat pngStagFormat; /**< Supported vulkan image format png write staging img */
+ VkImageTiling pngStagTiling; /**< tiling for the blit operation */
- mtx_t mutex; /**< protect device access (queue, cahes, ...)from ctxs in separate threads */
- bool threadAware; /**< if true, mutex is created and guard device queue and caches access */
- VkhQueue gQueue; /**< Vulkan Queue with Graphic flag */
+ mtx_t mutex; /**< protect device access (queue, cahes, ...)from ctxs in separate threads */
+ bool threadAware; /**< if true, mutex is created and guard device queue and caches access */
+ VkhQueue gQueue; /**< Vulkan Queue with Graphic flag */
- VkRenderPass renderPass; /**< Vulkan render pass, common for all surfaces */
- VkRenderPass renderPass_ClearStencil;/**< Vulkan render pass for first draw with context, stencil has to be cleared */
- VkRenderPass renderPass_ClearAll; /**< Vulkan render pass for new surface, clear all attacments*/
+ VkRenderPass renderPass; /**< Vulkan render pass, common for all surfaces */
+ VkRenderPass
+ renderPass_ClearStencil; /**< Vulkan render pass for first draw with context, stencil has to be cleared */
+ VkRenderPass renderPass_ClearAll; /**< Vulkan render pass for new surface, clear all attacments*/
- uint32_t references; /**< Reference count, prevent destroying device if still in use */
- VkCommandPool cmdPool; /**< Global command pool for processing on surfaces without context */
- VkCommandBuffer cmd; /**< Global command buffer */
- VkFence fence; /**< this fence is kept signaled when idle, wait and reset are called before each recording. */
+ uint32_t references; /**< Reference count, prevent destroying device if still in use */
+ VkCommandPool cmdPool; /**< Global command pool for processing on surfaces without context */
+ VkCommandBuffer cmd; /**< Global command buffer */
+ VkFence fence; /**< this fence is kept signaled when idle, wait and reset are called before each recording. */
- VkPipeline pipe_OVER; /**< default operator */
- VkPipeline pipe_SUB;
- VkPipeline pipe_CLEAR; /**< clear operator */
+ VkPipeline pipe_OVER; /**< default operator */
+ VkPipeline pipe_SUB;
+ VkPipeline pipe_CLEAR; /**< clear operator */
- VkPipeline pipelinePolyFill; /**< even-odd polygon filling first step */
- VkPipeline pipelineClipping; /**< draw on stencil to update clipping regions */
+ VkPipeline pipelinePolyFill; /**< even-odd polygon filling first step */
+ VkPipeline pipelineClipping; /**< draw on stencil to update clipping regions */
- VkPipelineCache pipelineCache; /**< speed up startup by caching configured pipelines on disk */
- VkPipelineLayout pipelineLayout; /**< layout common to all pipelines */
- VkDescriptorSetLayout dslFont; /**< font cache descriptors layout */
- VkDescriptorSetLayout dslSrc; /**< context source surface descriptors layout */
- VkDescriptorSetLayout dslGrad; /**< context gradient descriptors layout */
+ VkPipelineCache pipelineCache; /**< speed up startup by caching configured pipelines on disk */
+ VkPipelineLayout pipelineLayout; /**< layout common to all pipelines */
+ VkDescriptorSetLayout dslFont; /**< font cache descriptors layout */
+ VkDescriptorSetLayout dslSrc; /**< context source surface descriptors layout */
+ VkDescriptorSetLayout dslGrad; /**< context gradient descriptors layout */
- int hdpi, /**< only used for FreeType fonts and svg loading */
- vdpi;
+ int hdpi, /**< only used for FreeType fonts and svg loading */
+ vdpi;
- VkhDevice vkhDev; /**< old VkhDev created during vulkan context creation by @ref vkvg_device_create. */
+ VkhDevice vkhDev; /**< old VkhDev created during vulkan context creation by @ref vkvg_device_create. */
- VkhImage emptyImg; /**< prevent unbound descriptor to trigger Validation error 61 */
- VkSampleCountFlags samples; /**< samples count common to all surfaces */
- bool deferredResolve; /**< if true, resolve only on context destruction and set as source */
- vkvg_status_t status; /**< Current status of device, affected by last operation */
+ VkhImage emptyImg; /**< prevent unbound descriptor to trigger Validation error 61 */
+ VkSampleCountFlags samples; /**< samples count common to all surfaces */
+ bool deferredResolve; /**< if true, resolve only on context destruction and set as source */
+ vkvg_status_t status; /**< Current status of device, affected by last operation */
- _font_cache_t* fontCache; /**< Store everything relative to common font caching system */
+ _font_cache_t *fontCache; /**< Store everything relative to common font caching system */
- VkvgContext lastCtx; /**< last element of double linked list of context, used to trigger font caching system update on all contexts*/
+ VkvgContext lastCtx; /**< last element of double linked list of context, used to trigger font caching system update
+ on all contexts*/
- int32_t cachedContextMaxCount; /**< Maximum context cache element count.*/
- int32_t cachedContextCount; /**< Current context cache element count.*/
- _cached_ctx* cachedContextLast; /**< Last element of single linked list of saved context for fast reuse.*/
+ int32_t cachedContextMaxCount; /**< Maximum context cache element count.*/
+ int32_t cachedContextCount; /**< Current context cache element count.*/
+ _cached_ctx *cachedContextLast; /**< Last element of single linked list of saved context for fast reuse.*/
#ifdef VKVG_WIRED_DEBUG
- VkPipeline pipelineWired;
- VkPipeline pipelineLineList;
+ VkPipeline pipelineWired;
+ VkPipeline pipelineLineList;
#endif
#if VKVG_DBG_STATS
- vkvg_debug_stats_t debug_stats; /**< debug statistics on memory usage and vulkan ressources */
+ vkvg_debug_stats_t debug_stats; /**< debug statistics on memory usage and vulkan ressources */
#endif
-}vkvg_device;
-
-#define LOCK_DEVICE \
- if (dev->threadAware)\
- mtx_lock (&dev->mutex);
-#define UNLOCK_DEVICE \
- if (dev->threadAware)\
- mtx_unlock (&dev->mutex);
-
-bool _device_try_get_phyinfo (VkhPhyInfo* phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo* phy);
-bool _device_init_function_pointers (VkvgDevice dev);
-void _device_create_empty_texture (VkvgDevice dev, VkFormat format, VkImageTiling tiling);
-void _device_get_best_image_tiling (VkvgDevice dev, VkFormat format, VkImageTiling* pTiling);
-void _device_check_best_image_tiling (VkvgDevice dev, VkFormat format);
-void _device_create_pipeline_cache (VkvgDevice dev);
-VkRenderPass _device_createRenderPassMS (VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp);
-VkRenderPass _device_createRenderPassNoResolve(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp);
-void _device_setupPipelines (VkvgDevice dev);
-void _device_createDescriptorSetLayout (VkvgDevice dev);
-void _device_wait_idle (VkvgDevice dev);
-void _device_wait_and_reset_device_fence(VkvgDevice dev);
-void _device_submit_cmd (VkvgDevice dev, VkCommandBuffer* cmd, VkFence fence);
-
-bool _device_try_get_cached_context (VkvgDevice dev, VkvgContext* pCtx);
-void _device_store_context (VkvgContext ctx);
+} vkvg_device;
+
+#define LOCK_DEVICE \
+ if (dev->threadAware) \
+ mtx_lock(&dev->mutex);
+#define UNLOCK_DEVICE \
+ if (dev->threadAware) \
+ mtx_unlock(&dev->mutex);
+
+bool _device_try_get_phyinfo(VkhPhyInfo *phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo *phy);
+bool _device_init_function_pointers(VkvgDevice dev);
+void _device_create_empty_texture(VkvgDevice dev, VkFormat format, VkImageTiling tiling);
+void _device_get_best_image_tiling(VkvgDevice dev, VkFormat format, VkImageTiling *pTiling);
+void _device_check_best_image_tiling(VkvgDevice dev, VkFormat format);
+void _device_create_pipeline_cache(VkvgDevice dev);
+VkRenderPass _device_createRenderPassMS(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp);
+VkRenderPass _device_createRenderPassNoResolve(VkvgDevice dev, VkAttachmentLoadOp loadOp,
+ VkAttachmentLoadOp stencilLoadOp);
+void _device_setupPipelines(VkvgDevice dev);
+void _device_createDescriptorSetLayout(VkvgDevice dev);
+void _device_wait_idle(VkvgDevice dev);
+void _device_wait_and_reset_device_fence(VkvgDevice dev);
+void _device_submit_cmd(VkvgDevice dev, VkCommandBuffer *cmd, VkFence fence);
+
+bool _device_try_get_cached_context(VkvgDevice dev, VkvgContext *pCtx);
+void _device_store_context(VkvgContext ctx);
#endif
#include <string.h>
#include "vkvg_experimental.h"
#include "vkvg_context_internal.h"
-
-
-
#include <wchar.h>
#ifndef VKVG_USE_FREETYPE
- #define STB_TRUETYPE_IMPLEMENTATION
- #include "stb_truetype.h"
+#define STB_TRUETYPE_IMPLEMENTATION
+#include "stb_truetype.h"
#endif
-static int defaultFontCharSize = 12<<6;
+static int defaultFontCharSize = 12 << 6;
-void _fonts_cache_create (VkvgDevice dev){
- _font_cache_t* cache = (_font_cache_t*)calloc(1, sizeof(_font_cache_t));
+void _fonts_cache_create(VkvgDevice dev) {
+ _font_cache_t *cache = (_font_cache_t *)calloc(1, sizeof(_font_cache_t));
- if (dev->threadAware)
- mtx_init (&cache->mutex, mtx_plain);
+ if (dev->threadAware)
+ mtx_init(&cache->mutex, mtx_plain);
#ifdef VKVG_USE_FONTCONFIG
- cache->config = FcInitLoadConfigAndFonts ();
- if (!cache->config) {
- LOG(VKVG_LOG_DEBUG, "Font config initialisation failed, consider using 'FONTCONFIG_PATH' and 'FONTCONFIG_FILE' environmane\
+ cache->config = FcInitLoadConfigAndFonts();
+ if (!cache->config) {
+ LOG(VKVG_LOG_DEBUG,
+ "Font config initialisation failed, consider using 'FONTCONFIG_PATH' and 'FONTCONFIG_FILE' environmane\
variables to point to 'fonts.conf' needed for FontConfig startup");
- assert(cache->config);
- }
+ assert(cache->config);
+ }
#endif
#ifdef VKVG_USE_FREETYPE
- FT_CHECK_RESULT(FT_Init_FreeType(&cache->library));
+ FT_CHECK_RESULT(FT_Init_FreeType(&cache->library));
#endif
#if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
- FT_CHECK_RESULT(FT_Library_SetLcdFilter (cache->library, FT_LCD_FILTER_LIGHT));
- cache->texFormat = FB_COLOR_FORMAT;
- cache->texPixelSize = 4;
+ FT_CHECK_RESULT(FT_Library_SetLcdFilter(cache->library, FT_LCD_FILTER_LIGHT));
+ cache->texFormat = FB_COLOR_FORMAT;
+ cache->texPixelSize = 4;
#else
- cache->texFormat = VK_FORMAT_R8_UNORM;
- cache->texPixelSize = 1;
+ cache->texFormat = VK_FORMAT_R8_UNORM;
+ cache->texPixelSize = 1;
#endif
- cache->texLength = FONT_CACHE_INIT_LAYERS;
- cache->texture = vkh_tex2d_array_create ((VkhDevice)dev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE,
- cache->texLength ,VKH_MEMORY_USAGE_GPU_ONLY,
- VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
- vkh_image_create_descriptor (cache->texture, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
+ cache->texLength = FONT_CACHE_INIT_LAYERS;
+ cache->texture = vkh_tex2d_array_create(
+ (VkhDevice)dev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE, cache->texLength, VKH_MEMORY_USAGE_GPU_ONLY,
+ VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+ vkh_image_create_descriptor(cache->texture, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT,
+ VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
- cache->uploadFence = vkh_fence_create((VkhDevice)dev);
+ cache->uploadFence = vkh_fence_create((VkhDevice)dev);
- const uint32_t buffLength = FONT_PAGE_SIZE*FONT_PAGE_SIZE*cache->texPixelSize;
+ const uint32_t buffLength = FONT_PAGE_SIZE * FONT_PAGE_SIZE * cache->texPixelSize;
- vkh_buffer_init ((VkhDevice)dev,
- VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
- VKH_MEMORY_USAGE_CPU_TO_GPU,
- buffLength, &cache->buff, true);
+ vkh_buffer_init((VkhDevice)dev, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU, buffLength,
+ &cache->buff, true);
- cache->cmd = vkh_cmd_buff_create((VkhDevice)dev,dev->cmdPool,VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ cache->cmd = vkh_cmd_buff_create((VkhDevice)dev, dev->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
- //Set texture cache initial layout to shaderReadOnly to prevent error msg if cache is not fill
- const VkImageSubresourceRange subres = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,cache->texLength};
- vkh_cmd_begin (cache->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
- VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
- _device_submit_cmd (dev, &cache->cmd, cache->uploadFence);
+ // Set texture cache initial layout to shaderReadOnly to prevent error msg if cache is not fill
+ const VkImageSubresourceRange subres = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, cache->texLength};
+ vkh_cmd_begin(cache->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ vkh_image_set_layout_subres(cache->cmd, cache->texture, subres, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+ VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
+ _device_submit_cmd(dev, &cache->cmd, cache->uploadFence);
- cache->hostBuff = (uint8_t*)malloc(buffLength);
- cache->pensY = (int*)calloc(cache->texLength, sizeof(int));
+ cache->hostBuff = (uint8_t *)malloc(buffLength);
+ cache->pensY = (int *)calloc(cache->texLength, sizeof(int));
- dev->fontCache = cache;
+ dev->fontCache = cache;
}
-///increase layer count of 2d texture array used as font cache.
-void _increase_font_tex_array (VkvgDevice dev){
- LOG(VKVG_LOG_INFO, "_increase_font_tex_array\n");
+/// increase layer count of 2d texture array used as font cache.
+void _increase_font_tex_array(VkvgDevice dev) {
+ LOG(VKVG_LOG_INFO, "_increase_font_tex_array\n");
- _font_cache_t* cache = dev->fontCache;
+ _font_cache_t *cache = dev->fontCache;
- vkWaitForFences (dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
- ResetFences (dev->vkDev, 1, &cache->uploadFence);
+ vkWaitForFences(dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
+ ResetFences(dev->vkDev, 1, &cache->uploadFence);
- vkResetCommandBuffer(cache->cmd, 0);
+ vkResetCommandBuffer(cache->cmd, 0);
- uint8_t newSize = cache->texLength + FONT_CACHE_INIT_LAYERS;
- VkhImage newImg = vkh_tex2d_array_create ((VkhDevice)dev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE,
- newSize ,VKH_MEMORY_USAGE_GPU_ONLY,
- VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
- vkh_image_create_descriptor (newImg, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
+ uint8_t newSize = cache->texLength + FONT_CACHE_INIT_LAYERS;
+ VkhImage newImg = vkh_tex2d_array_create(
+ (VkhDevice)dev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE, newSize, VKH_MEMORY_USAGE_GPU_ONLY,
+ VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+ vkh_image_create_descriptor(newImg, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST,
+ VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
- VkImageSubresourceRange subresNew = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,newSize};
- VkImageSubresourceRange subres = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,cache->texLength};
+ VkImageSubresourceRange subresNew = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, newSize};
+ VkImageSubresourceRange subres = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, cache->texLength};
- vkh_cmd_begin (cache->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ vkh_cmd_begin(cache->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- vkh_image_set_layout_subres(cache->cmd, newImg, subresNew,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
- VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout_subres(cache->cmd, newImg, subresNew, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout_subres(cache->cmd, cache->texture, subres, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
- VkImageCopy cregion = { .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, cache->texLength},
- .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, cache->texLength},
- .extent = {FONT_PAGE_SIZE,FONT_PAGE_SIZE,1}};
+ VkImageCopy cregion = {.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, cache->texLength},
+ .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, cache->texLength},
+ .extent = {FONT_PAGE_SIZE, FONT_PAGE_SIZE, 1}};
- vkCmdCopyImage (cache->cmd, vkh_image_get_vkimage (cache->texture), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- vkh_image_get_vkimage (newImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cregion);
+ vkCmdCopyImage(cache->cmd, vkh_image_get_vkimage(cache->texture), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vkh_image_get_vkimage(newImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cregion);
- vkh_image_set_layout_subres(cache->cmd, newImg, subresNew,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
- vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+ vkh_image_set_layout_subres(cache->cmd, newImg, subresNew, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+ vkh_image_set_layout_subres(cache->cmd, cache->texture, subres, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
- VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
+ VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
- _device_submit_cmd (dev, &cache->cmd, cache->uploadFence);
- vkWaitForFences (dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
+ _device_submit_cmd(dev, &cache->cmd, cache->uploadFence);
+ vkWaitForFences(dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
- cache->pensY = (int*)realloc(cache->pensY, newSize * sizeof(int));
- void* tmp = memset (&cache->pensY[cache->texLength],0,FONT_CACHE_INIT_LAYERS*sizeof(int));
+ cache->pensY = (int *)realloc(cache->pensY, newSize * sizeof(int));
+ void *tmp = memset(&cache->pensY[cache->texLength], 0, FONT_CACHE_INIT_LAYERS * sizeof(int));
- vkh_image_destroy (cache->texture);
+ vkh_image_destroy(cache->texture);
- cache->texLength = newSize;
- cache->texture = newImg;
+ cache->texLength = newSize;
+ cache->texture = newImg;
- _device_wait_idle(dev);
+ _device_wait_idle(dev);
}
-//flush font stagging buffer to cache texture array
-//Trigger stagging buffer to be uploaded in font cache. Groupping upload improve performances.
-void _flush_chars_to_tex (VkvgDevice dev, _vkvg_font_t* f) {
+// flush font stagging buffer to cache texture array
+// Trigger stagging buffer to be uploaded in font cache. Groupping upload improve performances.
+void _flush_chars_to_tex(VkvgDevice dev, _vkvg_font_t *f) {
- _font_cache_t* cache = dev->fontCache;
- if (cache->stagingX == 0)//no char in stagging buff to flush
- return;
+ _font_cache_t *cache = dev->fontCache;
+ if (cache->stagingX == 0) // no char in stagging buff to flush
+ return;
- LOG(VKVG_LOG_INFO, "_flush_chars_to_tex pen(%d, %d)\n",f->curLine.penX, f->curLine.penY);
- vkWaitForFences (dev->vkDev,1,&cache->uploadFence,VK_TRUE,UINT64_MAX);
- ResetFences (dev->vkDev, 1, &cache->uploadFence);
+ LOG(VKVG_LOG_INFO, "_flush_chars_to_tex pen(%d, %d)\n", f->curLine.penX, f->curLine.penY);
+ vkWaitForFences(dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
+ ResetFences(dev->vkDev, 1, &cache->uploadFence);
- vkResetCommandBuffer(cache->cmd,0);
+ vkResetCommandBuffer(cache->cmd, 0);
- memcpy(vkh_buffer_get_mapped_pointer (&cache->buff), cache->hostBuff, (uint64_t)f->curLine.height * FONT_PAGE_SIZE * cache->texPixelSize);
+ memcpy(vkh_buffer_get_mapped_pointer(&cache->buff), cache->hostBuff,
+ (uint64_t)f->curLine.height * FONT_PAGE_SIZE * cache->texPixelSize);
- vkh_cmd_begin (cache->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ vkh_cmd_begin(cache->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- VkImageSubresourceRange subres = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,f->curLine.pageIdx,1};
- vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
- VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ VkImageSubresourceRange subres = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, f->curLine.pageIdx, 1};
+ vkh_image_set_layout_subres(cache->cmd, cache->texture, subres, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
- VkBufferImageCopy bufferCopyRegion = { .imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT,0,f->curLine.pageIdx,1},
- .bufferRowLength = FONT_PAGE_SIZE,
- .bufferImageHeight = f->curLine.height,
- .imageOffset = {f->curLine.penX,f->curLine.penY,0},
- .imageExtent = {FONT_PAGE_SIZE-f->curLine.penX,f->curLine.height,1}};
+ VkBufferImageCopy bufferCopyRegion = {.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, f->curLine.pageIdx, 1},
+ .bufferRowLength = FONT_PAGE_SIZE,
+ .bufferImageHeight = f->curLine.height,
+ .imageOffset = {f->curLine.penX, f->curLine.penY, 0},
+ .imageExtent = {FONT_PAGE_SIZE - f->curLine.penX, f->curLine.height, 1}};
- vkCmdCopyBufferToImage(cache->cmd, cache->buff.buffer,
- vkh_image_get_vkimage (cache->texture), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
+ vkCmdCopyBufferToImage(cache->cmd, cache->buff.buffer, vkh_image_get_vkimage(cache->texture),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
- vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+ vkh_image_set_layout_subres(cache->cmd, cache->texture, subres, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
- VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
+ VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
- _device_submit_cmd (dev, &cache->cmd, cache->uploadFence);
+ _device_submit_cmd(dev, &cache->cmd, cache->uploadFence);
- f->curLine.penX += cache->stagingX;
- cache->stagingX = 0;
- memset(cache->hostBuff, 0, (uint64_t)FONT_PAGE_SIZE * FONT_PAGE_SIZE * cache->texPixelSize);
+ f->curLine.penX += cache->stagingX;
+ cache->stagingX = 0;
+ memset(cache->hostBuff, 0, (uint64_t)FONT_PAGE_SIZE * FONT_PAGE_SIZE * cache->texPixelSize);
}
-///Start a new line in font cache, increase texture layer count if needed.
-void _init_next_line_in_tex_cache (VkvgDevice dev, _vkvg_font_t* f){
- _font_cache_t* cache = dev->fontCache;
- int i;
- for (i = 0; i < cache->texLength; ++i) {
- if (cache->pensY[i] + f->curLine.height >= FONT_PAGE_SIZE)
- continue;
- f->curLine.pageIdx = (unsigned char)i;
- f->curLine.penX = 0;
- f->curLine.penY = cache->pensY[i];
- cache->pensY[i] += f->curLine.height;
- return;
- }
- _flush_chars_to_tex (dev, f);
- _increase_font_tex_array (dev);
- _init_next_line_in_tex_cache(dev, f);
+/// Start a new line in font cache, increase texture layer count if needed.
+void _init_next_line_in_tex_cache(VkvgDevice dev, _vkvg_font_t *f) {
+ _font_cache_t *cache = dev->fontCache;
+ int i;
+ for (i = 0; i < cache->texLength; ++i) {
+ if (cache->pensY[i] + f->curLine.height >= FONT_PAGE_SIZE)
+ continue;
+ f->curLine.pageIdx = (unsigned char)i;
+ f->curLine.penX = 0;
+ f->curLine.penY = cache->pensY[i];
+ cache->pensY[i] += f->curLine.height;
+ return;
+ }
+ _flush_chars_to_tex(dev, f);
+ _increase_font_tex_array(dev);
+ _init_next_line_in_tex_cache(dev, f);
}
-void _font_cache_destroy (VkvgDevice dev){
- _font_cache_t* cache = (_font_cache_t*)dev->fontCache;
+void _font_cache_destroy(VkvgDevice dev) {
+ _font_cache_t *cache = (_font_cache_t *)dev->fontCache;
- free (cache->hostBuff);
+ free(cache->hostBuff);
- for (int i = 0; i < cache->fontsCount; ++i) {
- _vkvg_font_identity_t* f = &cache->fonts[i];
- for (uint32_t j = 0; j < f->sizeCount; j++) {
- _vkvg_font_t* s = &f->sizes[j];
+ for (int i = 0; i < cache->fontsCount; ++i) {
+ _vkvg_font_identity_t *f = &cache->fonts[i];
+ for (uint32_t j = 0; j < f->sizeCount; j++) {
+ _vkvg_font_t *s = &f->sizes[j];
#ifdef VKVG_USE_FREETYPE
- for (int g = 0; g < s->face->num_glyphs; ++g) {
- if (s->charLookup[g]!=NULL)
- free(s->charLookup[g]);
- }
- FT_Done_Face (s->face);
+ for (int g = 0; g < s->face->num_glyphs; ++g) {
+ if (s->charLookup[g] != NULL)
+ free(s->charLookup[g]);
+ }
+ FT_Done_Face(s->face);
#else
- for (int g = 0; g < f->stbInfo.numGlyphs; ++g) {
- if (s->charLookup[g]!=NULL)
- free(s->charLookup[g]);
- }
+ for (int g = 0; g < f->stbInfo.numGlyphs; ++g) {
+ if (s->charLookup[g] != NULL)
+ free(s->charLookup[g]);
+ }
#endif
#ifdef VKVG_USE_HARFBUZZ
- hb_font_destroy (s->hb_font);
+ hb_font_destroy(s->hb_font);
#endif
- free(s->charLookup);
- }
- free (f->sizes);
- free(f->fontFile);
- for (uint32_t j = 0; j < f->namesCount; j++)
- free (f->names[j]);
- if (f->namesCount > 0)
- free (f->names);
- free (f->fontBuffer);
- }
-
- free(cache->fonts);
- free(cache->pensY);
-
- vkh_buffer_reset (&cache->buff);
- vkh_image_destroy (cache->texture);
- //vkFreeCommandBuffers(dev->vkDev,dev->cmdPool, 1, &cache->cmd);
- vkDestroyFence (dev->vkDev,cache->uploadFence,NULL);
+ free(s->charLookup);
+ }
+ free(f->sizes);
+ free(f->fontFile);
+ for (uint32_t j = 0; j < f->namesCount; j++)
+ free(f->names[j]);
+ if (f->namesCount > 0)
+ free(f->names);
+ free(f->fontBuffer);
+ }
+
+ free(cache->fonts);
+ free(cache->pensY);
+
+ vkh_buffer_reset(&cache->buff);
+ vkh_image_destroy(cache->texture);
+ // vkFreeCommandBuffers(dev->vkDev,dev->cmdPool, 1, &cache->cmd);
+ vkDestroyFence(dev->vkDev, cache->uploadFence, NULL);
#ifdef VKVG_USE_FREETYPE
- FT_Done_FreeType(cache->library);
+ FT_Done_FreeType(cache->library);
#endif
#ifdef VKVG_USE_FONTCONFIG
- FcConfigDestroy(cache->config);
- FcFini();
+ FcConfigDestroy(cache->config);
+ FcFini();
#endif
- if (dev->threadAware)
- mtx_destroy (&cache->mutex);
-
- free (dev->fontCache);
+ if (dev->threadAware)
+ mtx_destroy(&cache->mutex);
+ free(dev->fontCache);
}
-void _font_cache_update_context_descset (VkvgContext ctx) {
- if (ctx->fontCacheImg)
- vkh_image_destroy (ctx->fontCacheImg);
+void _font_cache_update_context_descset(VkvgContext ctx) {
+ if (ctx->fontCacheImg)
+ vkh_image_destroy(ctx->fontCacheImg);
- LOCK_FONTCACHE (ctx->dev)
+ LOCK_FONTCACHE(ctx->dev)
- ctx->fontCacheImg = ctx->dev->fontCache->texture;
- vkh_image_reference (ctx->fontCacheImg);
+ ctx->fontCacheImg = ctx->dev->fontCache->texture;
+ vkh_image_reference(ctx->fontCacheImg);
- _update_descriptor_set (ctx, ctx->fontCacheImg, ctx->dsFont);
+ _update_descriptor_set(ctx, ctx->fontCacheImg, ctx->dsFont);
- UNLOCK_FONTCACHE (ctx->dev)
+ UNLOCK_FONTCACHE(ctx->dev)
}
-//create a new char entry and put glyph in stagging buffer, ready for upload.
-_char_ref* _prepare_char (VkvgDevice dev, VkvgText tr, uint32_t gindex){
- _vkvg_font_t* f = tr->font;
+// create a new char entry and put glyph in stagging buffer, ready for upload.
+_char_ref *_prepare_char(VkvgDevice dev, VkvgText tr, uint32_t gindex) {
+ _vkvg_font_t *f = tr->font;
#ifdef VKVG_USE_FREETYPE
- #if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
- FT_CHECK_RESULT(FT_Load_Glyph(f->face, gindex, FT_LOAD_TARGET_NORMAL));
- FT_CHECK_RESULT(FT_Render_Glyph(f->face->glyph, FT_RENDER_MODE_LCD));
- #else
- FT_CHECK_RESULT(FT_Load_Glyph(f->face, gindex, FT_LOAD_RENDER));
- #endif
-
- FT_GlyphSlot slot = f->face->glyph;
- FT_Bitmap bmp = slot->bitmap;
- uint32_t bmpByteWidth = bmp.width;
- uint32_t bmpPixelWidth = bmp.width;
- uint32_t bmpRows = bmp.rows;
- unsigned char* buffer = bmp.buffer;
+#if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
+ FT_CHECK_RESULT(FT_Load_Glyph(f->face, gindex, FT_LOAD_TARGET_NORMAL));
+ FT_CHECK_RESULT(FT_Render_Glyph(f->face->glyph, FT_RENDER_MODE_LCD));
+#else
+ FT_CHECK_RESULT(FT_Load_Glyph(f->face, gindex, FT_LOAD_RENDER));
+#endif
+
+ FT_GlyphSlot slot = f->face->glyph;
+ FT_Bitmap bmp = slot->bitmap;
+ uint32_t bmpByteWidth = bmp.width;
+ uint32_t bmpPixelWidth = bmp.width;
+ uint32_t bmpRows = bmp.rows;
+ unsigned char *buffer = bmp.buffer;
#if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
- bmpPixelWidth /= 3;
+ bmpPixelWidth /= 3;
#endif
#else
- stbtt_fontinfo* pStbInfo = &tr->fontId->stbInfo;
- int c_x1, c_y1, c_x2, c_y2;
- stbtt_GetGlyphBitmapBox (pStbInfo, gindex, f->scale, f->scale, &c_x1, &c_y1, &c_x2, &c_y2);
- uint32_t bmpByteWidth = c_x2 - c_x1;
- uint32_t bmpPixelWidth = bmpByteWidth;
- uint32_t bmpRows = c_y2 - c_y1;
+ stbtt_fontinfo *pStbInfo = &tr->fontId->stbInfo;
+ int c_x1, c_y1, c_x2, c_y2;
+ stbtt_GetGlyphBitmapBox(pStbInfo, gindex, f->scale, f->scale, &c_x1, &c_y1, &c_x2, &c_y2);
+ uint32_t bmpByteWidth = c_x2 - c_x1;
+ uint32_t bmpPixelWidth = bmpByteWidth;
+ uint32_t bmpRows = c_y2 - c_y1;
#endif
- uint8_t* data = dev->fontCache->hostBuff;
+ uint8_t *data = dev->fontCache->hostBuff;
- if (dev->fontCache->stagingX + f->curLine.penX + bmpPixelWidth > FONT_PAGE_SIZE){
- _flush_chars_to_tex (dev, f);
- _init_next_line_in_tex_cache (dev, f);
- }
+ if (dev->fontCache->stagingX + f->curLine.penX + bmpPixelWidth > FONT_PAGE_SIZE) {
+ _flush_chars_to_tex(dev, f);
+ _init_next_line_in_tex_cache(dev, f);
+ }
- _char_ref* cr = (_char_ref*)malloc(sizeof(_char_ref));
- int penX = dev->fontCache->stagingX;
+ _char_ref *cr = (_char_ref *)malloc(sizeof(_char_ref));
+ int penX = dev->fontCache->stagingX;
#ifdef VKVG_USE_FREETYPE
- for(uint32_t y=0; y < bmpRows; y++) {
- for(uint32_t x=0; x < bmpPixelWidth; x++) {
+ for (uint32_t y = 0; y < bmpRows; y++) {
+ for (uint32_t x = 0; x < bmpPixelWidth; x++) {
#if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
- unsigned char r = buffer[y * bmp.pitch + x * 3];
- unsigned char g = buffer[y * bmp.pitch + x * 3 + 1];
- unsigned char b = buffer[y * bmp.pitch + x * 3 + 2];
-
- data[(penX + x + y * FONT_PAGE_SIZE) * 4] = b;
- data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 1] = g;
- data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 2] = r;
- data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 3] = (r+g+b)/3;
+ unsigned char r = buffer[y * bmp.pitch + x * 3];
+ unsigned char g = buffer[y * bmp.pitch + x * 3 + 1];
+ unsigned char b = buffer[y * bmp.pitch + x * 3 + 2];
+
+ data[(penX + x + y * FONT_PAGE_SIZE) * 4] = b;
+ data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 1] = g;
+ data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 2] = r;
+ data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 3] = (r + g + b) / 3;
#else
- data[penX + x + y * FONT_PAGE_SIZE ] = buffer[x + y * bmpPixelWidth];
+ data[penX + x + y * FONT_PAGE_SIZE] = buffer[x + y * bmpPixelWidth];
#endif
- }
- }
- cr->bmpDiff.x = (int16_t)slot->bitmap_left;
- cr->bmpDiff.y = (int16_t)slot->bitmap_top;
- cr->advance = slot->advance;
+ }
+ }
+ cr->bmpDiff.x = (int16_t)slot->bitmap_left;
+ cr->bmpDiff.y = (int16_t)slot->bitmap_top;
+ cr->advance = slot->advance;
#else
- int advance;
- int lsb;
- stbtt_GetGlyphHMetrics(pStbInfo, gindex, &advance, &lsb);
- stbtt_MakeGlyphBitmap (pStbInfo, data + penX, bmpPixelWidth, bmpRows, FONT_PAGE_SIZE, f->scale, f->scale, gindex);
- cr->bmpDiff.x = (int16_t)c_x1;
- cr->bmpDiff.y = (int16_t)-c_y1;
- cr->advance = (vec2) {(uint32_t)roundf (f->scale * advance) << 6, 0};
+ int advance;
+ int lsb;
+ stbtt_GetGlyphHMetrics(pStbInfo, gindex, &advance, &lsb);
+ stbtt_MakeGlyphBitmap(pStbInfo, data + penX, bmpPixelWidth, bmpRows, FONT_PAGE_SIZE, f->scale, f->scale, gindex);
+ cr->bmpDiff.x = (int16_t)c_x1;
+ cr->bmpDiff.y = (int16_t)-c_y1;
+ cr->advance = (vec2){(uint32_t)roundf(f->scale * advance) << 6, 0};
#endif
- vec4 uvBounds = {
- {(float)(penX + f->curLine.penX) / (float)FONT_PAGE_SIZE},
- {(float)f->curLine.penY / (float)FONT_PAGE_SIZE},
- {(float)bmpPixelWidth},
- {(float)bmpRows}};
- cr->bounds = uvBounds;
- cr->pageIdx = f->curLine.pageIdx;
-
- f->charLookup[gindex] = cr;
- dev->fontCache->stagingX += bmpPixelWidth;
- return cr;
+ vec4 uvBounds = {{(float)(penX + f->curLine.penX) / (float)FONT_PAGE_SIZE},
+ {(float)f->curLine.penY / (float)FONT_PAGE_SIZE},
+ {(float)bmpPixelWidth},
+ {(float)bmpRows}};
+ cr->bounds = uvBounds;
+ cr->pageIdx = f->curLine.pageIdx;
+
+ f->charLookup[gindex] = cr;
+ dev->fontCache->stagingX += bmpPixelWidth;
+ return cr;
}
-void _font_add_name (_vkvg_font_identity_t* font, const char* name) {
- if (++font->namesCount == 1)
- font->names = (char**) malloc (sizeof(char*));
- else
- font->names = (char**) realloc (font->names, font->namesCount * sizeof(char*));
- font->names[font->namesCount-1] = (char*)calloc(strlen(name)+1, sizeof (char));
- strcpy (font->names[font->namesCount-1], name);
+void _font_add_name(_vkvg_font_identity_t *font, const char *name) {
+ if (++font->namesCount == 1)
+ font->names = (char **)malloc(sizeof(char *));
+ else
+ font->names = (char **)realloc(font->names, font->namesCount * sizeof(char *));
+ font->names[font->namesCount - 1] = (char *)calloc(strlen(name) + 1, sizeof(char));
+ strcpy(font->names[font->namesCount - 1], name);
}
-bool _font_cache_load_font_file_in_memory (_vkvg_font_identity_t* fontId) {
- FILE* fontFile = fopen(fontId->fontFile, "rb");
- if (!fontFile)
- return false;
- fseek(fontFile, 0, SEEK_END);
- fontId->fontBufSize = ftell(fontFile); /* how long is the file ? */
- fseek(fontFile, 0, SEEK_SET); /* reset */
- fontId->fontBuffer = malloc(fontId->fontBufSize);
- fread(fontId->fontBuffer, fontId->fontBufSize, 1, fontFile);
- fclose(fontFile);
- return true;
+bool _font_cache_load_font_file_in_memory(_vkvg_font_identity_t *fontId) {
+ FILE *fontFile = fopen(fontId->fontFile, "rb");
+ if (!fontFile)
+ return false;
+ fseek(fontFile, 0, SEEK_END);
+ fontId->fontBufSize = ftell(fontFile); /* how long is the file ? */
+ fseek(fontFile, 0, SEEK_SET); /* reset */
+ fontId->fontBuffer = malloc(fontId->fontBufSize);
+ fread(fontId->fontBuffer, fontId->fontBufSize, 1, fontFile);
+ fclose(fontFile);
+ return true;
}
-_vkvg_font_identity_t* _font_cache_add_font_identity (VkvgContext ctx, const char* fontFilePath, const char* name){
- _font_cache_t* cache = (_font_cache_t*)ctx->dev->fontCache;
- if (++cache->fontsCount == 1)
- cache->fonts = (_vkvg_font_identity_t*) malloc (cache->fontsCount * sizeof(_vkvg_font_identity_t));
- else
- cache->fonts = (_vkvg_font_identity_t*) realloc (cache->fonts, cache->fontsCount * sizeof(_vkvg_font_identity_t));
- _vkvg_font_identity_t nf = {0};
-
- if (fontFilePath) {
- int fflength = strlen (fontFilePath) + 1;
- nf.fontFile = (char*)malloc (fflength * sizeof(char));
- strcpy (nf.fontFile, fontFilePath);
- }
-
- _font_add_name (&nf, name);
-
- cache->fonts[cache->fontsCount-1] = nf;
- return &cache->fonts[cache->fontsCount-1];
+_vkvg_font_identity_t *_font_cache_add_font_identity(VkvgContext ctx, const char *fontFilePath, const char *name) {
+ _font_cache_t *cache = (_font_cache_t *)ctx->dev->fontCache;
+ if (++cache->fontsCount == 1)
+ cache->fonts = (_vkvg_font_identity_t *)malloc(cache->fontsCount * sizeof(_vkvg_font_identity_t));
+ else
+ cache->fonts =
+ (_vkvg_font_identity_t *)realloc(cache->fonts, cache->fontsCount * sizeof(_vkvg_font_identity_t));
+ _vkvg_font_identity_t nf = {0};
+
+ if (fontFilePath) {
+ int fflength = strlen(fontFilePath) + 1;
+ nf.fontFile = (char *)malloc(fflength * sizeof(char));
+ strcpy(nf.fontFile, fontFilePath);
+ }
+
+ _font_add_name(&nf, name);
+
+ cache->fonts[cache->fontsCount - 1] = nf;
+ return &cache->fonts[cache->fontsCount - 1];
}
-//select current font for context
-_vkvg_font_t* _find_or_create_font_size (VkvgContext ctx) {
- _vkvg_font_identity_t* font = ctx->currentFont;
-
- for (uint32_t i = 0; i < font->sizeCount; ++i) {
- if (font->sizes[i].charSize == ctx->selectedCharSize)
- return &font->sizes[i];
- }
- //if not found, create a new font size structure
- if (++font->sizeCount == 1)
- font->sizes = (_vkvg_font_t*) malloc (sizeof(_vkvg_font_t));
- else
- font->sizes = (_vkvg_font_t*) realloc (font->sizes, font->sizeCount * sizeof(_vkvg_font_t));
- _vkvg_font_t newSize = {.charSize = ctx->selectedCharSize};
-
- VkvgDevice dev = ctx->dev;
+// select current font for context
+_vkvg_font_t *_find_or_create_font_size(VkvgContext ctx) {
+ _vkvg_font_identity_t *font = ctx->currentFont;
+
+ for (uint32_t i = 0; i < font->sizeCount; ++i) {
+ if (font->sizes[i].charSize == ctx->selectedCharSize)
+ return &font->sizes[i];
+ }
+ // if not found, create a new font size structure
+ if (++font->sizeCount == 1)
+ font->sizes = (_vkvg_font_t *)malloc(sizeof(_vkvg_font_t));
+ else
+ font->sizes = (_vkvg_font_t *)realloc(font->sizes, font->sizeCount * sizeof(_vkvg_font_t));
+ _vkvg_font_t newSize = {.charSize = ctx->selectedCharSize};
+
+ VkvgDevice dev = ctx->dev;
#ifdef VKVG_USE_FREETYPE
- _font_cache_t* cache = (_font_cache_t*)ctx->dev->fontCache;
- FT_CHECK_RESULT(FT_New_Memory_Face (cache->library, font->fontBuffer, font->fontBufSize, 0, &newSize.face));
- FT_CHECK_RESULT(FT_Set_Char_Size(newSize.face, 0, newSize.charSize, dev->hdpi, dev->vdpi ));
+ _font_cache_t *cache = (_font_cache_t *)ctx->dev->fontCache;
+ FT_CHECK_RESULT(FT_New_Memory_Face(cache->library, font->fontBuffer, font->fontBufSize, 0, &newSize.face));
+ FT_CHECK_RESULT(FT_Set_Char_Size(newSize.face, 0, newSize.charSize, dev->hdpi, dev->vdpi));
- newSize.charLookup = (_char_ref**)calloc (newSize.face->num_glyphs, sizeof(_char_ref*));
+ newSize.charLookup = (_char_ref **)calloc(newSize.face->num_glyphs, sizeof(_char_ref *));
- if (FT_IS_SCALABLE(newSize.face))
- newSize.curLine.height = newSize.face->size->metrics.height >> 6;
- else
- newSize.curLine.height = newSize.face->height >> 6;
+ if (FT_IS_SCALABLE(newSize.face))
+ newSize.curLine.height = newSize.face->size->metrics.height >> 6;
+ else
+ newSize.curLine.height = newSize.face->height >> 6;
#else
- int result = stbtt_InitFont(&font->stbInfo, font->fontBuffer, 0);
- assert(result && "stbtt_initFont failed");
- if (!result) {
- ctx->status = VKVG_STATUS_INVALID_FONT;
- return NULL;
- }
- stbtt_GetFontVMetrics(&font->stbInfo, &font->ascent, &font->descent, &font->lineGap);
- newSize.charLookup = (_char_ref**)calloc (font->stbInfo.numGlyphs, sizeof(_char_ref*));
- //newSize.scale = stbtt_ScaleForPixelHeight(&font->stbInfo, newSize.charSize);
- newSize.scale = stbtt_ScaleForMappingEmToPixels(&font->stbInfo, newSize.charSize);
- newSize.curLine.height = roundf (newSize.scale * (font->ascent - font->descent + font->lineGap));
- newSize.ascent = roundf (newSize.scale * font->ascent);
- newSize.descent = roundf (newSize.scale * font->descent);
- newSize.lineGap = roundf (newSize.scale * font->lineGap);
+ int result = stbtt_InitFont(&font->stbInfo, font->fontBuffer, 0);
+ assert(result && "stbtt_initFont failed");
+ if (!result) {
+ ctx->status = VKVG_STATUS_INVALID_FONT;
+ return NULL;
+ }
+ stbtt_GetFontVMetrics(&font->stbInfo, &font->ascent, &font->descent, &font->lineGap);
+ newSize.charLookup = (_char_ref **)calloc(font->stbInfo.numGlyphs, sizeof(_char_ref *));
+ // newSize.scale = stbtt_ScaleForPixelHeight(&font->stbInfo, newSize.charSize);
+ newSize.scale = stbtt_ScaleForMappingEmToPixels(&font->stbInfo, newSize.charSize);
+ newSize.curLine.height = roundf(newSize.scale * (font->ascent - font->descent + font->lineGap));
+ newSize.ascent = roundf(newSize.scale * font->ascent);
+ newSize.descent = roundf(newSize.scale * font->descent);
+ newSize.lineGap = roundf(newSize.scale * font->lineGap);
#endif
#ifdef VKVG_USE_HARFBUZZ
- newSize.hb_font = hb_ft_font_create(newSize.face, NULL);
+ newSize.hb_font = hb_ft_font_create(newSize.face, NULL);
#endif
- _init_next_line_in_tex_cache (dev, &newSize);
+ _init_next_line_in_tex_cache(dev, &newSize);
- font->sizes[font->sizeCount-1] = newSize;
- return &font->sizes[font->sizeCount-1];
+ font->sizes[font->sizeCount - 1] = newSize;
+ return &font->sizes[font->sizeCount - 1];
}
-//try find font already resolved with fontconfig by font name
-bool _tryFindFontByName (VkvgContext ctx, _vkvg_font_identity_t** font){
- _font_cache_t* cache = ctx->dev->fontCache;
- for (int i = 0; i < cache->fontsCount; ++i) {
- for (uint32_t j = 0; j < cache->fonts[i].namesCount; j++) {
- if (strcmp (cache->fonts[i].names[j], ctx->selectedFontName) == 0) {
- *font = &cache->fonts[i];
- return true;
- }
- }
- }
- return false;
+// try find font already resolved with fontconfig by font name
+bool _tryFindFontByName(VkvgContext ctx, _vkvg_font_identity_t **font) {
+ _font_cache_t *cache = ctx->dev->fontCache;
+ for (int i = 0; i < cache->fontsCount; ++i) {
+ for (uint32_t j = 0; j < cache->fonts[i].namesCount; j++) {
+ if (strcmp(cache->fonts[i].names[j], ctx->selectedFontName) == 0) {
+ *font = &cache->fonts[i];
+ return true;
+ }
+ }
+ }
+ return false;
}
#ifdef VKVG_USE_FONTCONFIG
-bool _tryResolveFontNameWithFontConfig (VkvgContext ctx, _vkvg_font_identity_t** resolvedFont) {
- _font_cache_t* cache = (_font_cache_t*)ctx->dev->fontCache;
- char* fontFile = NULL;
-
- FcPattern* pat = FcNameParse((const FcChar8*)ctx->selectedFontName);
- FcConfigSubstitute(cache->config, pat, FcMatchPattern);
- FcDefaultSubstitute(pat);
- FcResult result;
- FcPattern* font = FcFontMatch(cache->config, pat, &result);
- if (font)
- FcPatternGetString(font, FC_FILE, 0, (FcChar8 **)&fontFile);
- *resolvedFont = NULL;
- if (fontFile) {
- //try find font in cache by path
- for (int i = 0; i < cache->fontsCount; ++i) {
- if (cache->fonts[i].fontFile && strcmp (cache->fonts[i].fontFile, fontFile) == 0) {
- _font_add_name (&cache->fonts[i], ctx->selectedFontName);
- *resolvedFont = &cache->fonts[i];
- break;
- }
- }
- if (!*resolvedFont) {
- //if not found, create a new vkvg_font
- _vkvg_font_identity_t* fid = _font_cache_add_font_identity(ctx, fontFile, ctx->selectedFontName);
- _font_cache_load_font_file_in_memory (fid);
- *resolvedFont = &cache->fonts[cache->fontsCount-1];
- }
- }
-
- FcPatternDestroy(pat);
- FcPatternDestroy(font);
-
- return (fontFile != NULL);
+bool _tryResolveFontNameWithFontConfig(VkvgContext ctx, _vkvg_font_identity_t **resolvedFont) {
+ _font_cache_t *cache = (_font_cache_t *)ctx->dev->fontCache;
+ char *fontFile = NULL;
+
+ FcPattern *pat = FcNameParse((const FcChar8 *)ctx->selectedFontName);
+ FcConfigSubstitute(cache->config, pat, FcMatchPattern);
+ FcDefaultSubstitute(pat);
+ FcResult result;
+ FcPattern *font = FcFontMatch(cache->config, pat, &result);
+ if (font)
+ FcPatternGetString(font, FC_FILE, 0, (FcChar8 **)&fontFile);
+ *resolvedFont = NULL;
+ if (fontFile) {
+ // try find font in cache by path
+ for (int i = 0; i < cache->fontsCount; ++i) {
+ if (cache->fonts[i].fontFile && strcmp(cache->fonts[i].fontFile, fontFile) == 0) {
+ _font_add_name(&cache->fonts[i], ctx->selectedFontName);
+ *resolvedFont = &cache->fonts[i];
+ break;
+ }
+ }
+ if (!*resolvedFont) {
+ // if not found, create a new vkvg_font
+ _vkvg_font_identity_t *fid = _font_cache_add_font_identity(ctx, fontFile, ctx->selectedFontName);
+ _font_cache_load_font_file_in_memory(fid);
+ *resolvedFont = &cache->fonts[cache->fontsCount - 1];
+ }
+ }
+
+ FcPatternDestroy(pat);
+ FcPatternDestroy(font);
+
+ return (fontFile != NULL);
}
#endif
+// try to find corresponding font in cache (defined by context selectedFont) and create a new font entry if not found.
+void _update_current_font(VkvgContext ctx) {
+ if (ctx->currentFont == NULL) {
+ LOCK_FONTCACHE(ctx->dev)
+ if (ctx->selectedFontName[0] == 0)
+ _select_font_face(ctx, "sans");
-//try to find corresponding font in cache (defined by context selectedFont) and create a new font entry if not found.
-void _update_current_font (VkvgContext ctx) {
- if (ctx->currentFont == NULL){
- LOCK_FONTCACHE(ctx->dev)
- if (ctx->selectedFontName[0] == 0)
- _select_font_face (ctx, "sans");
-
- if (!_tryFindFontByName (ctx, &ctx->currentFont)) {
+ if (!_tryFindFontByName(ctx, &ctx->currentFont)) {
#ifdef VKVG_USE_FONTCONFIG
- _tryResolveFontNameWithFontConfig (ctx, &ctx->currentFont);
+ _tryResolveFontNameWithFontConfig(ctx, &ctx->currentFont);
#else
- LOG(VKVG_LOG_ERR, "Unresolved font: %s\n", ctx->selectedFontName);
- UNLOCK_FONTCACHE(ctx->dev)
- ctx->status = VKVG_STATUS_INVALID_FONT;
- return;
+ LOG(VKVG_LOG_ERR, "Unresolved font: %s\n", ctx->selectedFontName);
+ UNLOCK_FONTCACHE(ctx->dev)
+ ctx->status = VKVG_STATUS_INVALID_FONT;
+ return;
#endif
- }
+ }
- ctx->currentFontSize = _find_or_create_font_size (ctx);
- UNLOCK_FONTCACHE(ctx->dev)
- }
+ ctx->currentFontSize = _find_or_create_font_size(ctx);
+ UNLOCK_FONTCACHE(ctx->dev)
+ }
}
#ifdef VKVG_USE_HARFBUZZ
-//Get harfBuzz buffer for provided text.
-hb_buffer_t * _get_hb_buffer (_vkvg_font_t* font, const char* text, int length) {
- hb_buffer_t *buf = hb_buffer_create();
+// Get harfBuzz buffer for provided text.
+hb_buffer_t *_get_hb_buffer(_vkvg_font_t *font, const char *text, int length) {
+ hb_buffer_t *buf = hb_buffer_create();
- hb_script_t script = HB_SCRIPT_LATIN;
- hb_unicode_funcs_t* ucfunc = hb_unicode_funcs_get_default ();
- wchar_t firstChar = 0;
- if (mbstowcs (&firstChar, text, 1))
- script = hb_unicode_script (ucfunc, firstChar);
+ hb_script_t script = HB_SCRIPT_LATIN;
+ hb_unicode_funcs_t *ucfunc = hb_unicode_funcs_get_default();
+ wchar_t firstChar = 0;
+ if (mbstowcs(&firstChar, text, 1))
+ script = hb_unicode_script(ucfunc, firstChar);
- hb_direction_t dir = hb_script_get_horizontal_direction(script);
- hb_buffer_set_direction (buf, dir);
- hb_buffer_set_script (buf, script);
- //hb_buffer_set_language (buf, hb_language_from_string (lng, (int)strlen(lng)));
- hb_buffer_add_utf8 (buf, text, length, 0, length);
+ hb_direction_t dir = hb_script_get_horizontal_direction(script);
+ hb_buffer_set_direction(buf, dir);
+ hb_buffer_set_script(buf, script);
+ // hb_buffer_set_language (buf, hb_language_from_string (lng, (int)strlen(lng)));
+ hb_buffer_add_utf8(buf, text, length, 0, length);
- hb_shape (font->hb_font, buf, NULL, 0);
+ hb_shape(font->hb_font, buf, NULL, 0);
- return buf;
+ return buf;
}
#endif
-//retrieve global font extends of context's current font as defined by FreeType
-void _font_cache_font_extents (VkvgContext ctx, vkvg_font_extents_t *extents) {
- _update_current_font (ctx);
+// retrieve global font extends of context's current font as defined by FreeType
+void _font_cache_font_extents(VkvgContext ctx, vkvg_font_extents_t *extents) {
+ _update_current_font(ctx);
- if (ctx->status)
- return;
+ if (ctx->status)
+ return;
- //TODO: ensure correct metrics are returned (scalled/unscalled, etc..)
- _vkvg_font_t* font = ctx->currentFontSize;
+ // TODO: ensure correct metrics are returned (scalled/unscalled, etc..)
+ _vkvg_font_t *font = ctx->currentFontSize;
#ifdef VKVG_USE_FREETYPE
- FT_BBox* bbox = &font->face->bbox;
- FT_Size_Metrics* metrics = &font->face->size->metrics;
-
- extents->ascent = (float)(FT_MulFix(font->face->ascender, metrics->y_scale) >> 6);//metrics->ascender >> 6;
- extents->descent =-(float)(FT_MulFix(font->face->descender, metrics->y_scale) >> 6);//metrics->descender >> 6;
- extents->height = (float)(FT_MulFix(font->face->height, metrics->y_scale) >> 6);//metrics->height >> 6;
- extents->max_x_advance = (float)(bbox->xMax >> 6);
- extents->max_y_advance = (float)(bbox->yMax >> 6);
+ FT_BBox *bbox = &font->face->bbox;
+ FT_Size_Metrics *metrics = &font->face->size->metrics;
+
+ extents->ascent = (float)(FT_MulFix(font->face->ascender, metrics->y_scale) >> 6); // metrics->ascender >> 6;
+ extents->descent = -(float)(FT_MulFix(font->face->descender, metrics->y_scale) >> 6); // metrics->descender >> 6;
+ extents->height = (float)(FT_MulFix(font->face->height, metrics->y_scale) >> 6); // metrics->height >> 6;
+ extents->max_x_advance = (float)(bbox->xMax >> 6);
+ extents->max_y_advance = (float)(bbox->yMax >> 6);
#else
- extents->ascent = roundf (font->scale * ctx->currentFont->ascent);
- extents->descent =-roundf (font->scale * ctx->currentFont->descent);
- extents->height = roundf (font->scale * (ctx->currentFont->ascent - ctx->currentFont->descent + ctx->currentFont->lineGap));
- extents->max_x_advance = 0;//TODO
- extents->max_y_advance = 0;
+ extents->ascent = roundf(font->scale * ctx->currentFont->ascent);
+ extents->descent = -roundf(font->scale * ctx->currentFont->descent);
+ extents->height =
+ roundf(font->scale * (ctx->currentFont->ascent - ctx->currentFont->descent + ctx->currentFont->lineGap));
+ extents->max_x_advance = 0; // TODO
+ extents->max_y_advance = 0;
#endif
}
-//compute text extends for provided string.
-void _font_cache_text_extents (VkvgContext ctx, const char* text, int length, vkvg_text_extents_t *extents) {
- if (text == NULL) {
- memset(extents, 0, sizeof(vkvg_text_extents_t));
- return;
- }
+// compute text extends for provided string.
+void _font_cache_text_extents(VkvgContext ctx, const char *text, int length, vkvg_text_extents_t *extents) {
+ if (text == NULL) {
+ memset(extents, 0, sizeof(vkvg_text_extents_t));
+ return;
+ }
- vkvg_text_run_t tr = {0};
- _font_cache_create_text_run (ctx, text, length, &tr);
+ vkvg_text_run_t tr = {0};
+ _font_cache_create_text_run(ctx, text, length, &tr);
- if (ctx->status)
- return;
+ if (ctx->status)
+ return;
- *extents = tr.extents;
+ *extents = tr.extents;
- _font_cache_destroy_text_run (&tr);
+ _font_cache_destroy_text_run(&tr);
}
-//text is expected as utf8 encoded
-//if length is < 0, text must be null terminated, else it contains glyph count
-void _font_cache_create_text_run (VkvgContext ctx, const char* text, int length, VkvgText textRun) {
+// text is expected as utf8 encoded
+// if length is < 0, text must be null terminated, else it contains glyph count
+void _font_cache_create_text_run(VkvgContext ctx, const char *text, int length, VkvgText textRun) {
- _update_current_font (ctx);
+ _update_current_font(ctx);
- if (ctx->status)
- return;
+ if (ctx->status)
+ return;
- textRun->fontId = ctx->currentFont;
- textRun->font = ctx->currentFontSize;
- textRun->dev = ctx->dev;
+ textRun->fontId = ctx->currentFont;
+ textRun->font = ctx->currentFontSize;
+ textRun->dev = ctx->dev;
- LOCK_FONTCACHE (ctx->dev)
+ LOCK_FONTCACHE(ctx->dev)
#ifdef VKVG_USE_HARFBUZZ
- textRun->hbBuf = _get_hb_buffer (ctx->currentFontSize, text, length);
- textRun->glyphs = hb_buffer_get_glyph_positions (textRun->hbBuf, &textRun->glyph_count);
+ textRun->hbBuf = _get_hb_buffer(ctx->currentFontSize, text, length);
+ textRun->glyphs = hb_buffer_get_glyph_positions(textRun->hbBuf, &textRun->glyph_count);
#else
- size_t wsize;
- if (length < 0)
- wsize = mbstowcs(NULL, text, 0);
- else
- wsize = (size_t)length;
- wchar_t *tmp = (wchar_t*)malloc((wsize+1) * sizeof (wchar_t));
- textRun->glyph_count = mbstowcs (tmp, text, wsize);
- textRun->glyphs = (vkvg_glyph_info_t*)malloc(textRun->glyph_count * sizeof (vkvg_glyph_info_t));
- for (unsigned int i=0; i<textRun->glyph_count; i++) {
+ size_t wsize;
+ if (length < 0)
+ wsize = mbstowcs(NULL, text, 0);
+ else
+ wsize = (size_t)length;
+ wchar_t *tmp = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t));
+ textRun->glyph_count = mbstowcs(tmp, text, wsize);
+ textRun->glyphs = (vkvg_glyph_info_t *)malloc(textRun->glyph_count * sizeof(vkvg_glyph_info_t));
+ for (unsigned int i = 0; i < textRun->glyph_count; i++) {
#ifdef VKVG_USE_FREETYPE
- uint32_t gindex = FT_Get_Char_Index (textRun->font->face, tmp[i]);
+ uint32_t gindex = FT_Get_Char_Index(textRun->font->face, tmp[i]);
#else
- uint32_t gindex = stbtt_FindGlyphIndex (&textRun->fontId->stbInfo, tmp[i]);
+ uint32_t gindex = stbtt_FindGlyphIndex(&textRun->fontId->stbInfo, tmp[i]);
#endif
- _char_ref* cr = textRun->font->charLookup[gindex];
- if (cr==NULL)
- cr = _prepare_char (textRun->dev, textRun, gindex);
- textRun->glyphs[i].codepoint = gindex;
- textRun->glyphs[i].x_advance = cr->advance.x;
- textRun->glyphs[i].y_advance = cr->advance.y;
- textRun->glyphs[i].x_offset = 0;
- textRun->glyphs[i].y_offset = 0;
- /*textRun->glyphs[i].x_offset = cr->bmpDiff.x;
- textRun->glyphs[i].y_offset = cr->bmpDiff.y;*/
- }
- free (tmp);
+ _char_ref *cr = textRun->font->charLookup[gindex];
+ if (cr == NULL)
+ cr = _prepare_char(textRun->dev, textRun, gindex);
+ textRun->glyphs[i].codepoint = gindex;
+ textRun->glyphs[i].x_advance = cr->advance.x;
+ textRun->glyphs[i].y_advance = cr->advance.y;
+ textRun->glyphs[i].x_offset = 0;
+ textRun->glyphs[i].y_offset = 0;
+ /*textRun->glyphs[i].x_offset = cr->bmpDiff.x;
+ textRun->glyphs[i].y_offset = cr->bmpDiff.y;*/
+ }
+ free(tmp);
#endif
-
- UNLOCK_FONTCACHE (ctx->dev)
- unsigned int string_width_in_pixels = 0;
- for (uint32_t i=0; i < textRun->glyph_count; ++i)
- string_width_in_pixels += textRun->glyphs[i].x_advance >> 6;
+ UNLOCK_FONTCACHE(ctx->dev)
+
+ unsigned int string_width_in_pixels = 0;
+ for (uint32_t i = 0; i < textRun->glyph_count; ++i)
+ string_width_in_pixels += textRun->glyphs[i].x_advance >> 6;
#ifdef VKVG_USE_FREETYPE
- FT_Size_Metrics* metrics = &ctx->currentFontSize->face->size->metrics;
- textRun->extents.height = (float)(FT_MulFix(ctx->currentFontSize->face->height, metrics->y_scale) >> 6);// (metrics->ascender + metrics->descender) >> 6;
+ FT_Size_Metrics *metrics = &ctx->currentFontSize->face->size->metrics;
+ textRun->extents.height = (float)(FT_MulFix(ctx->currentFontSize->face->height, metrics->y_scale) >>
+ 6); // (metrics->ascender + metrics->descender) >> 6;
#else
- textRun->extents.height = textRun->font->ascent - textRun->font->descent + textRun->font->lineGap;
+ textRun->extents.height = textRun->font->ascent - textRun->font->descent + textRun->font->lineGap;
#endif
- textRun->extents.x_advance = (float)string_width_in_pixels;
- if (textRun->glyph_count > 0) {
- textRun->extents.y_advance = (float)(textRun->glyphs[textRun->glyph_count-1].y_advance >> 6);
- textRun->extents.x_bearing = -(float)(textRun->glyphs[0].x_offset >> 6);
- textRun->extents.y_bearing = -(float)(textRun->glyphs[0].y_offset >> 6);
- }
-
- textRun->extents.width = textRun->extents.x_advance;
+ textRun->extents.x_advance = (float)string_width_in_pixels;
+ if (textRun->glyph_count > 0) {
+ textRun->extents.y_advance = (float)(textRun->glyphs[textRun->glyph_count - 1].y_advance >> 6);
+ textRun->extents.x_bearing = -(float)(textRun->glyphs[0].x_offset >> 6);
+ textRun->extents.y_bearing = -(float)(textRun->glyphs[0].y_offset >> 6);
+ }
+
+ textRun->extents.width = textRun->extents.x_advance;
}
-void _font_cache_destroy_text_run (VkvgText textRun) {
+void _font_cache_destroy_text_run(VkvgText textRun) {
#ifdef VKVG_USE_HARFBUZZ
- hb_buffer_destroy (textRun->hbBuf);
+ hb_buffer_destroy(textRun->hbBuf);
#else
- if (textRun->glyph_count > 0)
- free (textRun->glyphs);
+ if (textRun->glyph_count > 0)
+ free(textRun->glyphs);
#endif
}
#ifdef DEBUG
-void _show_texture (vkvg_context* ctx){
- Vertex vs[] = {
- {{0,0}, 0, {0,0,0}},
- {{0,FONT_PAGE_SIZE}, 0, {0,1,0}},
- {{FONT_PAGE_SIZE,0}, 0, {1,0,0}},
- {{FONT_PAGE_SIZE,FONT_PAGE_SIZE}, 0, {1,1,0}}
- };
-
- VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
- Vertex* pVert = &ctx->vertexCache[ctx->vertCount];
- memcpy (pVert,vs,4*sizeof(Vertex));
- ctx->vertCount+=4;
-
- _check_vertex_cache_size(ctx);
-
- _add_tri_indices_for_rect(ctx, firstIdx);
+void _show_texture(vkvg_context *ctx) {
+ Vertex vs[] = {{{0, 0}, 0, {0, 0, 0}},
+ {{0, FONT_PAGE_SIZE}, 0, {0, 1, 0}},
+ {{FONT_PAGE_SIZE, 0}, 0, {1, 0, 0}},
+ {{FONT_PAGE_SIZE, FONT_PAGE_SIZE}, 0, {1, 1, 0}}};
+
+ VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+ Vertex *pVert = &ctx->vertexCache[ctx->vertCount];
+ memcpy(pVert, vs, 4 * sizeof(Vertex));
+ ctx->vertCount += 4;
+
+ _check_vertex_cache_size(ctx);
+
+ _add_tri_indices_for_rect(ctx, firstIdx);
}
#endif
-void _font_cache_show_text_run (VkvgContext ctx, VkvgText tr) {
- unsigned int glyph_count;
+void _font_cache_show_text_run(VkvgContext ctx, VkvgText tr) {
+ unsigned int glyph_count;
#ifdef VKVG_USE_HARFBUZZ
- hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos (tr->hbBuf, &glyph_count);
+ hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(tr->hbBuf, &glyph_count);
#else
- vkvg_glyph_info_t* glyph_info = tr->glyphs;
- glyph_count = tr->glyph_count;
+ vkvg_glyph_info_t *glyph_info = tr->glyphs;
+ glyph_count = tr->glyph_count;
#endif
- Vertex v = {{0},ctx->curColor,{0,0,-1}};
- vec2 pen = {0,0};
+ Vertex v = {{0}, ctx->curColor, {0, 0, -1}};
+ vec2 pen = {0, 0};
- if (!_current_path_is_empty(ctx))
- pen = _get_current_position(ctx);
+ if (!_current_path_is_empty(ctx))
+ pen = _get_current_position(ctx);
- LOCK_FONTCACHE (ctx->dev)
+ LOCK_FONTCACHE(ctx->dev)
- for (uint32_t i=0; i < glyph_count; ++i) {
- _char_ref* cr = tr->font->charLookup[glyph_info[i].codepoint];
+ for (uint32_t i = 0; i < glyph_count; ++i) {
+ _char_ref *cr = tr->font->charLookup[glyph_info[i].codepoint];
#ifdef VKVG_USE_HARFBUZZ
- if (cr==NULL)
- cr = _prepare_char(tr->dev, tr, glyph_info[i].codepoint);
+ if (cr == NULL)
+ cr = _prepare_char(tr->dev, tr, glyph_info[i].codepoint);
#endif
- float uvWidth = cr->bounds.width / (float)FONT_PAGE_SIZE;
- float uvHeight = cr->bounds.height / (float)FONT_PAGE_SIZE;
- vec2 p0 = {pen.x + cr->bmpDiff.x + (tr->glyphs[i].x_offset >> 6),
- pen.y - cr->bmpDiff.y + (tr->glyphs[i].y_offset >> 6)};
- v.pos = p0;
-
- VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
-
-
- v.uv.x = cr->bounds.x;
- v.uv.y = cr->bounds.y;
- v.uv.z = cr->pageIdx;
- _add_vertex(ctx,v);
-
- v.pos.y += cr->bounds.height;
- v.uv.y += uvHeight;
- _add_vertex(ctx,v);
-
- v.pos.x += cr->bounds.width;
- v.pos.y = p0.y;
- v.uv.x += uvWidth;
- v.uv.y = cr->bounds.y;
- _add_vertex(ctx,v);
-
- v.pos.y += cr->bounds.height;
- v.uv.y += uvHeight;
- _add_vertex(ctx,v);
-
- _add_tri_indices_for_rect (ctx, firstIdx);
-
- pen.x += (tr->glyphs[i].x_advance >> 6);
- pen.y -= (tr->glyphs[i].y_advance >> 6);
- }
-
- //equivalent to a moveto
- _finish_path(ctx);
- _add_point (ctx, pen.x, pen.y);
- _flush_chars_to_tex(tr->dev, tr->font);
- UNLOCK_FONTCACHE (ctx->dev)
-
- if (ctx->fontCacheImg != ctx->dev->fontCache->texture) {
- vkvg_flush (ctx);
- _font_cache_update_context_descset (ctx);
- }
+ float uvWidth = cr->bounds.width / (float)FONT_PAGE_SIZE;
+ float uvHeight = cr->bounds.height / (float)FONT_PAGE_SIZE;
+ vec2 p0 = {pen.x + cr->bmpDiff.x + (tr->glyphs[i].x_offset >> 6),
+ pen.y - cr->bmpDiff.y + (tr->glyphs[i].y_offset >> 6)};
+ v.pos = p0;
+
+ VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+
+ v.uv.x = cr->bounds.x;
+ v.uv.y = cr->bounds.y;
+ v.uv.z = cr->pageIdx;
+ _add_vertex(ctx, v);
+
+ v.pos.y += cr->bounds.height;
+ v.uv.y += uvHeight;
+ _add_vertex(ctx, v);
+
+ v.pos.x += cr->bounds.width;
+ v.pos.y = p0.y;
+ v.uv.x += uvWidth;
+ v.uv.y = cr->bounds.y;
+ _add_vertex(ctx, v);
+
+ v.pos.y += cr->bounds.height;
+ v.uv.y += uvHeight;
+ _add_vertex(ctx, v);
+
+ _add_tri_indices_for_rect(ctx, firstIdx);
+
+ pen.x += (tr->glyphs[i].x_advance >> 6);
+ pen.y -= (tr->glyphs[i].y_advance >> 6);
+ }
+
+ // equivalent to a moveto
+ _finish_path(ctx);
+ _add_point(ctx, pen.x, pen.y);
+ _flush_chars_to_tex(tr->dev, tr->font);
+ UNLOCK_FONTCACHE(ctx->dev)
+
+ if (ctx->fontCacheImg != ctx->dev->fontCache->texture) {
+ vkvg_flush(ctx);
+ _font_cache_update_context_descset(ctx);
+ }
}
-void _font_cache_show_text (VkvgContext ctx, const char* text){
+void _font_cache_show_text(VkvgContext ctx, const char *text) {
- vkvg_text_run_t tr = {0};
- _font_cache_create_text_run (ctx, text, -1, &tr);
+ vkvg_text_run_t tr = {0};
+ _font_cache_create_text_run(ctx, text, -1, &tr);
- if (ctx->status)
- return;
+ if (ctx->status)
+ return;
- _font_cache_show_text_run (ctx, &tr);
+ _font_cache_show_text_run(ctx, &tr);
- _font_cache_destroy_text_run (&tr);
+ _font_cache_destroy_text_run(&tr);
- //_show_texture(ctx); return;
+ //_show_texture(ctx); return;
}
-
/*void testfonts(){
- FT_Library library;
- FT_Face face;
- FT_GlyphSlot slot;
+ FT_Library library;
+ FT_Face face;
+ FT_GlyphSlot slot;
- assert(!FT_Init_FreeType(&library));
- assert(!FT_New_Face(library, "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 0, &face));
- assert(!FT_Set_Char_Size(face, 0, ptSize, device_hdpi, device_vdpi ));
+ assert(!FT_Init_FreeType(&library));
+ assert(!FT_New_Face(library, "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 0, &face));
+ assert(!FT_Set_Char_Size(face, 0, ptSize, device_hdpi, device_vdpi ));
- //_build_face_tex(face);
+ //_build_face_tex(face);
- hb_font_t *hb_font = hb_ft_font_create(face, NULL);
- hb_buffer_t *buf = hb_buffer_create();
+ hb_font_t *hb_font = hb_ft_font_create(face, NULL);
+ hb_buffer_t *buf = hb_buffer_create();
- const char *text = "Ленивый рыжий кот";
- const char *lng = "en";
- //"كسول الزنجبيل القط","懶惰的姜貓",
+ const char *text = "Ленивый рыжий кот";
+ const char *lng = "en";
+ //"كسول الزنجبيل القط","懶惰的姜貓",
- hb_buffer_set_direction (buf, HB_DIRECTION_LTR);
- hb_buffer_set_script (buf, HB_SCRIPT_LATIN);
- hb_buffer_set_language (buf, hb_language_from_string(lng,strlen(lng)));
- hb_buffer_add_utf8 (buf, text, strlen(text), 0, strlen(text));
+ hb_buffer_set_direction (buf, HB_DIRECTION_LTR);
+ hb_buffer_set_script (buf, HB_SCRIPT_LATIN);
+ hb_buffer_set_language (buf, hb_language_from_string(lng,strlen(lng)));
+ hb_buffer_add_utf8 (buf, text, strlen(text), 0, strlen(text));
- hb_unicode_funcs_t * unifc = hb_unicode_funcs_get_default();
- hb_script_t sc = hb_buffer_get_script(buf);
+ hb_unicode_funcs_t * unifc = hb_unicode_funcs_get_default();
+ hb_script_t sc = hb_buffer_get_script(buf);
- sc = hb_unicode_script(unifc,0x0260);
+ sc = hb_unicode_script(unifc,0x0260);
- FT_CharMap* cm = face->charmap;
+ FT_CharMap* cm = face->charmap;
- //hb_script_to_iso15924_tag()
+ //hb_script_to_iso15924_tag()
- FT_Done_Face ( face );
- FT_Done_FreeType( library );
+ FT_Done_Face ( face );
+ FT_Done_FreeType( library );
}*/
#ifndef VKVG_FONTS_H
#define VKVG_FONTS_H
- //disable warning on iostream functions on windows
+// disable warning on iostream functions on windows
#define _CRT_SECURE_NO_WARNINGS
#ifdef VKVG_USE_FREETYPE
- #include <ft2build.h>
- #include FT_FREETYPE_H
- #if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
- #include <freetype/ftlcdfil.h>
- #endif
- #define FT_CHECK_RESULT(f) \
- { \
- FT_Error res = (f); \
- if (res != 0) \
- { \
- fprintf(stderr,"Fatal : FreeType error is %d in %s at line %d\n", res, __FILE__, __LINE__); \
- assert(res == 0); \
- } \
- }
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
+#include <freetype/ftlcdfil.h>
+#endif
+#define FT_CHECK_RESULT(f) \
+ { \
+ FT_Error res = (f); \
+ if (res != 0) { \
+ fprintf(stderr, "Fatal : FreeType error is %d in %s at line %d\n", res, __FILE__, __LINE__); \
+ assert(res == 0); \
+ } \
+ }
#else
- #include "stb_truetype.h"
+#include "stb_truetype.h"
#endif
#ifdef VKVG_USE_HARFBUZZ
- #include <harfbuzz/hb.h>
- #include <harfbuzz/hb-ft.h>
+#include <harfbuzz/hb.h>
+#include <harfbuzz/hb-ft.h>
#else
#endif
#ifdef VKVG_USE_FONTCONFIG
- #include <fontconfig/fontconfig.h>
+#include <fontconfig/fontconfig.h>
#endif
-#define FONT_PAGE_SIZE 1024
-#define FONT_CACHE_INIT_LAYERS 1
+#define FONT_PAGE_SIZE 1024
+#define FONT_CACHE_INIT_LAYERS 1
#define FONT_FILE_NAME_MAX_SIZE 1024
-#define FONT_NAME_MAX_SIZE 128
+#define FONT_NAME_MAX_SIZE 128
#include "vkvg_internal.h"
#include "vkh_buffer.h"
-//texture coordinates of one character in font cache array texture.
+// texture coordinates of one character in font cache array texture.
typedef struct {
- vec4 bounds; /* normalized float bounds of character bitmap in font cache texture. */
- vec2i16 bmpDiff; /* Difference in pixel between char bitmap top left corner and char glyph*/
- uint8_t pageIdx; /* Page index in font cache texture array */
+ vec4 bounds; /* normalized float bounds of character bitmap in font cache texture. */
+ vec2i16 bmpDiff; /* Difference in pixel between char bitmap top left corner and char glyph*/
+ uint8_t pageIdx; /* Page index in font cache texture array */
#ifdef VKVG_USE_FREETYPE
- FT_Vector advance; /* horizontal or vertical advance */
+ FT_Vector advance; /* horizontal or vertical advance */
#else
- vec2 advance;
+ vec2 advance;
#endif
-}_char_ref;
+} _char_ref;
// Current location in font cache texture array for new character addition. Each font holds such structure to locate
// where to upload new chars.
typedef struct {
- uint8_t pageIdx; /* Current page number in font cache */
- int penX; /* Current X in cache for next char addition */
- int penY; /* Current Y in cache for next char addition */
- int height; /* Height of current line pointed by this structure */
-}_tex_ref_t;
-
-// Loaded font structure, one per size, holds informations for glyphes upload in cache and the lookup table of characters.
+ uint8_t pageIdx; /* Current page number in font cache */
+ int penX; /* Current X in cache for next char addition */
+ int penY; /* Current Y in cache for next char addition */
+ int height; /* Height of current line pointed by this structure */
+} _tex_ref_t;
+
+// Loaded font structure, one per size, holds informations for glyphes upload in cache and the lookup table of
+// characters.
typedef struct {
#ifdef VKVG_USE_FREETYPE
- FT_F26Dot6 charSize; /* Font size*/
- FT_Face face; /* FreeType face*/
+ FT_F26Dot6 charSize; /* Font size*/
+ FT_Face face; /* FreeType face*/
#else
- uint32_t charSize; /* Font size in pixel */
- float scale; /* scale factor for the given size */
- int ascent; /* unscalled stb font metrics */
- int descent;
- int lineGap;
+ uint32_t charSize; /* Font size in pixel */
+ float scale; /* scale factor for the given size */
+ int ascent; /* unscalled stb font metrics */
+ int descent;
+ int lineGap;
#endif
#ifdef VKVG_USE_HARFBUZZ
- hb_font_t* hb_font; /* HarfBuzz font instance*/
+ hb_font_t *hb_font; /* HarfBuzz font instance*/
#endif
- _char_ref** charLookup; /* Lookup table of characteres in cache, if not found, upload is queued*/
+ _char_ref **charLookup; /* Lookup table of characteres in cache, if not found, upload is queued*/
- _tex_ref_t curLine; /* tex coord where to add new char bmp's */
-}_vkvg_font_t;
+ _tex_ref_t curLine; /* tex coord where to add new char bmp's */
+} _vkvg_font_t;
/* Font identification structure */
typedef struct {
- char** names; /* Resolved Input names to this font by fontConfig or custom name set by @ref vkvg_load_from_path*/
- uint32_t namesCount; /* Count of resolved names by fontConfig */
- unsigned char* fontBuffer; /* stb_truetype in memory buffer */
- long fontBufSize;/* */
- char* fontFile; /* Font file full path*/
+ char **names; /* Resolved Input names to this font by fontConfig or custom name set by @ref vkvg_load_from_path*/
+ uint32_t namesCount; /* Count of resolved names by fontConfig */
+ unsigned char *fontBuffer; /* stb_truetype in memory buffer */
+ long fontBufSize; /* */
+ char *fontFile; /* Font file full path*/
#ifndef VKVG_USE_FREETYPE
- stbtt_fontinfo stbInfo; /* stb_truetype structure */
- int ascent; /* unscalled stb font metrics */
- int descent;
- int lineGap;
+ stbtt_fontinfo stbInfo; /* stb_truetype structure */
+ int ascent; /* unscalled stb font metrics */
+ int descent;
+ int lineGap;
#endif
- uint32_t sizeCount; /* available font size loaded */
- _vkvg_font_t* sizes; /* loaded font size array */
-}_vkvg_font_identity_t;
+ uint32_t sizeCount; /* available font size loaded */
+ _vkvg_font_t *sizes; /* loaded font size array */
+} _vkvg_font_identity_t;
// Font cache global structure, entry point for all font related operations.
typedef struct {
#ifdef VKVG_USE_FREETYPE
- FT_Library library; /* FreeType library*/
+ FT_Library library; /* FreeType library*/
#else
#endif
#ifdef VKVG_USE_FONTCONFIG
- FcConfig* config; /* Font config, used to find font files by font names*/
+ FcConfig *config; /* Font config, used to find font files by font names*/
#endif
- int stagingX; /* x pen in host buffer */
- uint8_t* hostBuff; /* host memory where bitmaps are first loaded */
-
- VkCommandBuffer cmd; /* vulkan command buffer for font textures upload */
- vkh_buffer_t buff; /* stagin buffer */
- VkhImage texture; /* 2d array texture used by contexts to draw characteres */
- VkFormat texFormat; /* Format of the fonts texture array */
- uint8_t texPixelSize; /* Size in byte of a single pixel in a font texture */
- uint8_t texLength; /* layer count of 2d array texture, starts with FONT_CACHE_INIT_LAYERS count and increased when needed */
- int* pensY; /* array of current y pen positions for each texture in cache 2d array */
- VkFence uploadFence; /* Signaled when upload is finished */
- mtx_t mutex; /* font cache global mutex, used only if device is in thread aware mode (see: vkvg_device_set_thread_aware) */
-
- _vkvg_font_identity_t* fonts; /* Loaded fonts structure array */
- int32_t fontsCount; /* Loaded fonts array count*/
-}_font_cache_t;
-
-#define LOCK_FONTCACHE(dev) \
- if (dev->threadAware)\
- mtx_lock (&dev->fontCache->mutex);
-#define UNLOCK_FONTCACHE(dev) \
- if (dev->threadAware)\
- mtx_unlock (&dev->fontCache->mutex);
+ int stagingX; /* x pen in host buffer */
+ uint8_t *hostBuff; /* host memory where bitmaps are first loaded */
+
+ VkCommandBuffer cmd; /* vulkan command buffer for font textures upload */
+ vkh_buffer_t buff; /* stagin buffer */
+ VkhImage texture; /* 2d array texture used by contexts to draw characteres */
+ VkFormat texFormat; /* Format of the fonts texture array */
+ uint8_t texPixelSize; /* Size in byte of a single pixel in a font texture */
+ uint8_t texLength; /* layer count of 2d array texture, starts with FONT_CACHE_INIT_LAYERS count and increased when
+ needed */
+ int *pensY; /* array of current y pen positions for each texture in cache 2d array */
+ VkFence uploadFence; /* Signaled when upload is finished */
+ mtx_t mutex; /* font cache global mutex, used only if device is in thread aware mode (see:
+ vkvg_device_set_thread_aware) */
+
+ _vkvg_font_identity_t *fonts; /* Loaded fonts structure array */
+ int32_t fontsCount; /* Loaded fonts array count*/
+} _font_cache_t;
+
+#define LOCK_FONTCACHE(dev) \
+ if (dev->threadAware) \
+ mtx_lock(&dev->fontCache->mutex);
+#define UNLOCK_FONTCACHE(dev) \
+ if (dev->threadAware) \
+ mtx_unlock(&dev->fontCache->mutex);
// Precompute everything necessary to measure and draw one line of text, usefull to draw the same text multiple times.
typedef struct _vkvg_text_run_t {
- _vkvg_font_identity_t* fontId; /* vkvg font structure pointer */
- _vkvg_font_t* font; /* vkvg font structure pointer */
- VkvgDevice dev; /* vkvg device associated with this text run */
- vkvg_text_extents_t extents; /* store computed text extends */
- const char* text; /* utf8 char array of text*/
- unsigned int glyph_count;/* Total glyph count */
+ _vkvg_font_identity_t *fontId; /* vkvg font structure pointer */
+ _vkvg_font_t *font; /* vkvg font structure pointer */
+ VkvgDevice dev; /* vkvg device associated with this text run */
+ vkvg_text_extents_t extents; /* store computed text extends */
+ const char *text; /* utf8 char array of text*/
+ unsigned int glyph_count; /* Total glyph count */
#ifdef VKVG_USE_HARFBUZZ
- hb_buffer_t* hbBuf; /* HarfBuzz buffer of text */
- hb_glyph_position_t* glyphs; /* HarfBuzz computed glyph positions array */
+ hb_buffer_t *hbBuf; /* HarfBuzz buffer of text */
+ hb_glyph_position_t *glyphs; /* HarfBuzz computed glyph positions array */
#else
- vkvg_glyph_info_t* glyphs; /* computed glyph positions array */
+ vkvg_glyph_info_t *glyphs; /* computed glyph positions array */
#endif
} vkvg_text_run_t;
-//Create font cache.
-void _fonts_cache_create (VkvgDevice dev);
-//Release all ressources of font cache.
-void _font_cache_destroy (VkvgDevice dev);
-_vkvg_font_identity_t *_font_cache_add_font_identity (VkvgContext ctx, const char* fontFile, const char *name);
-bool _font_cache_load_font_file_in_memory (_vkvg_font_identity_t* fontId);
-//Draw text
-void _font_cache_show_text (VkvgContext ctx, const char* text);
-//Get text dimmensions
-void _font_cache_text_extents (VkvgContext ctx, const char* text, int length, vkvg_text_extents_t *extents);
-//Get font global dimmensions
-void _font_cache_font_extents (VkvgContext ctx, vkvg_font_extents_t* extents);
-//Create text object that could be drawn multiple times minimizing harfbuzz and compute processing.
-void _font_cache_create_text_run (VkvgContext ctx, const char* text, int length, VkvgText textRun);
-//Release ressources held by a text run.
-void _font_cache_destroy_text_run (VkvgText textRun);
-//Draw text run
-void _font_cache_show_text_run (VkvgContext ctx, VkvgText tr);
-//update context font cache descriptor set
-void _font_cache_update_context_descset (VkvgContext ctx);
+// Create font cache.
+void _fonts_cache_create(VkvgDevice dev);
+// Release all ressources of font cache.
+void _font_cache_destroy(VkvgDevice dev);
+_vkvg_font_identity_t *_font_cache_add_font_identity(VkvgContext ctx, const char *fontFile, const char *name);
+bool _font_cache_load_font_file_in_memory(_vkvg_font_identity_t *fontId);
+// Draw text
+void _font_cache_show_text(VkvgContext ctx, const char *text);
+// Get text dimmensions
+void _font_cache_text_extents(VkvgContext ctx, const char *text, int length, vkvg_text_extents_t *extents);
+// Get font global dimmensions
+void _font_cache_font_extents(VkvgContext ctx, vkvg_font_extents_t *extents);
+// Create text object that could be drawn multiple times minimizing harfbuzz and compute processing.
+void _font_cache_create_text_run(VkvgContext ctx, const char *text, int length, VkvgText textRun);
+// Release ressources held by a text run.
+void _font_cache_destroy_text_run(VkvgText textRun);
+// Draw text run
+void _font_cache_show_text_run(VkvgContext ctx, VkvgText tr);
+// update context font cache descriptor set
+void _font_cache_update_context_descset(VkvgContext ctx);
#endif
#ifndef VKVG_INTERNAL_H
#define VKVG_INTERNAL_H
- //disable warning on iostream functions on windows
+// disable warning on iostream functions on windows
#define _CRT_SECURE_NO_WARNINGS
#include <assert.h>
#include <float.h>
#include <stdbool.h>
#include <stdint.h>
-#include <stdio.h> // needed before stdarg.h on Windows
+#include <stdio.h> // needed before stdarg.h on Windows
#include <stdarg.h>
#include <string.h>
#include <math.h>
#ifndef M_PIF
- #define M_PIF 3.14159265358979323846f /* float pi */
- #define M_PIF_2 1.57079632679489661923f
- #define M_2_PIF 0.63661977236758134308f // 2/pi
+#define M_PIF 3.14159265358979323846f /* float pi */
+#define M_PIF_2 1.57079632679489661923f
+#define M_2_PIF 0.63661977236758134308f // 2/pi
#endif
/*#ifndef M_2_PI
- #define M_2_PI 0.63661977236758134308 // 2/pi
+ #define M_2_PI 0.63661977236758134308 // 2/pi
#endif*/
#ifdef DEBUG
-#define LOG(level,...) { \
- if ((vkvg_log_level) & (level)) \
- fprintf (stdout, __VA_ARGS__); \
-}
+#define LOG(level, ...) \
+ { \
+ if ((vkvg_log_level) & (level)) \
+ fprintf(stdout, __VA_ARGS__); \
+ }
#else
#define LOG
#endif
-#define PATH_CLOSED_BIT 0x80000000 /* most significant bit of path elmts is closed/open path state */
-#define PATH_HAS_CURVES_BIT 0x40000000 /* 2rd most significant bit of path elmts is curved status
- * for main path, this indicate that curve datas are present.
- * For segments, this indicate that the segment is curved or not */
-#define PATH_IS_CONVEX_BIT 0x20000000 /* simple rectangle or circle. */
-#define PATH_ELT_MASK 0x1FFFFFFF /* Bit mask for fetching path element value */
+#define PATH_CLOSED_BIT 0x80000000 /* most significant bit of path elmts is closed/open path state */
+#define PATH_HAS_CURVES_BIT \
+ 0x40000000 /* 2rd most significant bit of path elmts is curved status \
+ * for main path, this indicate that curve datas are present. \
+ * For segments, this indicate that the segment is curved or not */
+#define PATH_IS_CONVEX_BIT 0x20000000 /* simple rectangle or circle. */
+#define PATH_ELT_MASK 0x1FFFFFFF /* Bit mask for fetching path element value */
-#define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c)))
-#define ROUND_DOWN(v,p) (floorf(v * p) / p)
-#define EQUF(a, b) (fabsf(a-(b))<=FLT_EPSILON)
+#define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c)))
+#define ROUND_DOWN(v, p) (floorf(v * p) / p)
+#define EQUF(a, b) (fabsf(a - (b)) <= FLT_EPSILON)
#ifndef MAX
- #define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
- #define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#include "deps/tinycthread.h"
#include "cross_os.h"
-//width of the stencil buffer will determine the number of context saving/restore layers
-//the two first bits of the stencil are the FILL and the CLIP bits, all other bits are
-//used to store clipping bit on context saving. 8 bit stencil will allow 6 save/restore layer
+// width of the stencil buffer will determine the number of context saving/restore layers
+// the two first bits of the stencil are the FILL and the CLIP bits, all other bits are
+// used to store clipping bit on context saving. 8 bit stencil will allow 6 save/restore layer
#define FB_COLOR_FORMAT VK_FORMAT_B8G8R8A8_UNORM
-#define VKVG_SURFACE_IMGS_REQUIREMENTS (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT|VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT|\
- VK_FORMAT_FEATURE_TRANSFER_DST_BIT|VK_FORMAT_FEATURE_TRANSFER_SRC_BIT|VK_FORMAT_FEATURE_BLIT_SRC_BIT)
-#define VKVG_PNG_WRITE_IMG_REQUIREMENTS (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT|VK_FORMAT_FEATURE_TRANSFER_DST_BIT|VK_FORMAT_FEATURE_BLIT_DST_BIT)
-//30 seconds fence timeout
+#define VKVG_SURFACE_IMGS_REQUIREMENTS \
+ (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | \
+ VK_FORMAT_FEATURE_TRANSFER_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT)
+#define VKVG_PNG_WRITE_IMG_REQUIREMENTS \
+ (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT)
+// 30 seconds fence timeout
#define VKVG_FENCE_TIMEOUT 30000000000
-//#define VKVG_FENCE_TIMEOUT 10000
+// #define VKVG_FENCE_TIMEOUT 10000
#include "vkvg.h"
#include "vkh.h"
#include "vectors.h"
/*typedef struct {
- vkvg_status_t status;
+ vkvg_status_t status;
} _vkvg_no_mem_struct;*/
static vkvg_status_t _no_mem_status = VKVG_STATUS_NO_MEMORY;
* THE SOFTWARE.
*/
-//most of the matrix logic is grabbed from cairo, so here is the
-//licence:
+// most of the matrix logic is grabbed from cairo, so here is the
+// licence:
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
-//matrix computations mainly taken from http://cairographics.org
-static void _vkvg_matrix_scalar_multiply (vkvg_matrix_t *matrix, float scalar)
-{
- matrix->xx *= scalar;
- matrix->yx *= scalar;
+// matrix computations mainly taken from http://cairographics.org
+static void _vkvg_matrix_scalar_multiply(vkvg_matrix_t *matrix, float scalar) {
+ matrix->xx *= scalar;
+ matrix->yx *= scalar;
- matrix->xy *= scalar;
- matrix->yy *= scalar;
+ matrix->xy *= scalar;
+ matrix->yy *= scalar;
- matrix->x0 *= scalar;
- matrix->y0 *= scalar;
+ matrix->x0 *= scalar;
+ matrix->y0 *= scalar;
}
-void _vkvg_matrix_get_affine (const vkvg_matrix_t *matrix,
- float *xx, float *yx,
- float *xy, float *yy,
- float *x0, float *y0)
-{
- *xx = matrix->xx;
- *yx = matrix->yx;
-
- *xy = matrix->xy;
- *yy = matrix->yy;
-
- if (x0)
- *x0 = matrix->x0;
- if (y0)
- *y0 = matrix->y0;
+void _vkvg_matrix_get_affine(const vkvg_matrix_t *matrix, float *xx, float *yx, float *xy, float *yy, float *x0,
+ float *y0) {
+ *xx = matrix->xx;
+ *yx = matrix->yx;
+
+ *xy = matrix->xy;
+ *yy = matrix->yy;
+
+ if (x0)
+ *x0 = matrix->x0;
+ if (y0)
+ *y0 = matrix->y0;
}
-static void _vkvg_matrix_compute_adjoint (vkvg_matrix_t *matrix)
-{
- /* adj (A) = transpose (C:cofactor (A,i,j)) */
- float a, b, c, d, tx, ty;
-
- _vkvg_matrix_get_affine (matrix,
- &a, &b,
- &c, &d,
- &tx, &ty);
-
- vkvg_matrix_init (matrix,
- d, -b,
- -c, a,
- c*ty - d*tx, b*tx - a*ty);
+static void _vkvg_matrix_compute_adjoint(vkvg_matrix_t *matrix) {
+ /* adj (A) = transpose (C:cofactor (A,i,j)) */
+ float a, b, c, d, tx, ty;
+
+ _vkvg_matrix_get_affine(matrix, &a, &b, &c, &d, &tx, &ty);
+
+ vkvg_matrix_init(matrix, d, -b, -c, a, c * ty - d * tx, b * tx - a * ty);
}
-float _vkvg_matrix_compute_determinant (const vkvg_matrix_t *matrix)
-{
- float a, b, c, d;
+float _vkvg_matrix_compute_determinant(const vkvg_matrix_t *matrix) {
+ float a, b, c, d;
- a = matrix->xx; b = matrix->yx;
- c = matrix->xy; d = matrix->yy;
+ a = matrix->xx;
+ b = matrix->yx;
+ c = matrix->xy;
+ d = matrix->yy;
- return a*d - b*c;
+ return a * d - b * c;
}
-vkvg_status_t vkvg_matrix_invert (vkvg_matrix_t *matrix)
-{
- float det;
+vkvg_status_t vkvg_matrix_invert(vkvg_matrix_t *matrix) {
+ float det;
- /* Simple scaling|translation matrices are quite common... */
- if (matrix->xy == 0. && matrix->yx == 0.) {
- matrix->x0 = -matrix->x0;
- matrix->y0 = -matrix->y0;
+ /* Simple scaling|translation matrices are quite common... */
+ if (matrix->xy == 0. && matrix->yx == 0.) {
+ matrix->x0 = -matrix->x0;
+ matrix->y0 = -matrix->y0;
- if (matrix->xx != 1.f) {
- if (matrix->xx == 0.)
- return VKVG_STATUS_INVALID_MATRIX;
+ if (matrix->xx != 1.f) {
+ if (matrix->xx == 0.)
+ return VKVG_STATUS_INVALID_MATRIX;
- matrix->xx = 1.f / matrix->xx;
- matrix->x0 *= matrix->xx;
- }
+ matrix->xx = 1.f / matrix->xx;
+ matrix->x0 *= matrix->xx;
+ }
- if (matrix->yy != 1.f) {
- if (matrix->yy == 0.)
- return VKVG_STATUS_INVALID_MATRIX;
+ if (matrix->yy != 1.f) {
+ if (matrix->yy == 0.)
+ return VKVG_STATUS_INVALID_MATRIX;
- matrix->yy = 1.f / matrix->yy;
- matrix->y0 *= matrix->yy;
- }
+ matrix->yy = 1.f / matrix->yy;
+ matrix->y0 *= matrix->yy;
+ }
- return VKVG_STATUS_SUCCESS;
- }
+ return VKVG_STATUS_SUCCESS;
+ }
- /* inv (A) = 1/det (A) * adj (A) */
- det = _vkvg_matrix_compute_determinant (matrix);
+ /* inv (A) = 1/det (A) * adj (A) */
+ det = _vkvg_matrix_compute_determinant(matrix);
- if (! ISFINITE (det))
- return VKVG_STATUS_INVALID_MATRIX;
+ if (!ISFINITE(det))
+ return VKVG_STATUS_INVALID_MATRIX;
- if (det == 0)
- return VKVG_STATUS_INVALID_MATRIX;
+ if (det == 0)
+ return VKVG_STATUS_INVALID_MATRIX;
- _vkvg_matrix_compute_adjoint (matrix);
- _vkvg_matrix_scalar_multiply (matrix, 1 / det);
+ _vkvg_matrix_compute_adjoint(matrix);
+ _vkvg_matrix_scalar_multiply(matrix, 1 / det);
- return VKVG_STATUS_SUCCESS;
-}
-void vkvg_matrix_init_identity (vkvg_matrix_t *matrix)
-{
- vkvg_matrix_init (matrix,
- 1, 0,
- 0, 1,
- 0, 0);
+ return VKVG_STATUS_SUCCESS;
}
+void vkvg_matrix_init_identity(vkvg_matrix_t *matrix) { vkvg_matrix_init(matrix, 1, 0, 0, 1, 0, 0); }
-void vkvg_matrix_init (vkvg_matrix_t *matrix,
- float xx, float yx,
- float xy, float yy,
- float x0, float y0)
-{
- matrix->xx = xx; matrix->yx = yx;
- matrix->xy = xy; matrix->yy = yy;
- matrix->x0 = x0; matrix->y0 = y0;
+void vkvg_matrix_init(vkvg_matrix_t *matrix, float xx, float yx, float xy, float yy, float x0, float y0) {
+ matrix->xx = xx;
+ matrix->yx = yx;
+ matrix->xy = xy;
+ matrix->yy = yy;
+ matrix->x0 = x0;
+ matrix->y0 = y0;
}
-void vkvg_matrix_init_translate (vkvg_matrix_t *matrix, float tx, float ty)
-{
- vkvg_matrix_init (matrix,
- 1, 0,
- 0, 1,
- tx, ty);
-}
-void vkvg_matrix_init_scale (vkvg_matrix_t *matrix, float sx, float sy)
-{
- vkvg_matrix_init (matrix,
- sx, 0,
- 0, sy,
- 0, 0);
+void vkvg_matrix_init_translate(vkvg_matrix_t *matrix, float tx, float ty) {
+ vkvg_matrix_init(matrix, 1, 0, 0, 1, tx, ty);
}
-void vkvg_matrix_init_rotate (vkvg_matrix_t *matrix, float radians)
-{
- float s;
- float c;
-
- s = sinf (radians);
- c = cosf (radians);
-
- vkvg_matrix_init (matrix,
- c, s,
- -s, c,
- 0, 0);
+void vkvg_matrix_init_scale(vkvg_matrix_t *matrix, float sx, float sy) { vkvg_matrix_init(matrix, sx, 0, 0, sy, 0, 0); }
+void vkvg_matrix_init_rotate(vkvg_matrix_t *matrix, float radians) {
+ float s;
+ float c;
+
+ s = sinf(radians);
+ c = cosf(radians);
+
+ vkvg_matrix_init(matrix, c, s, -s, c, 0, 0);
}
-void vkvg_matrix_translate (vkvg_matrix_t *matrix, float tx, float ty)
-{
- vkvg_matrix_t tmp;
+void vkvg_matrix_translate(vkvg_matrix_t *matrix, float tx, float ty) {
+ vkvg_matrix_t tmp;
- vkvg_matrix_init_translate (&tmp, tx, ty);
+ vkvg_matrix_init_translate(&tmp, tx, ty);
- vkvg_matrix_multiply (matrix, &tmp, matrix);
+ vkvg_matrix_multiply(matrix, &tmp, matrix);
}
-void vkvg_matrix_scale (vkvg_matrix_t *matrix, float sx, float sy)
-{
- vkvg_matrix_t tmp;
+void vkvg_matrix_scale(vkvg_matrix_t *matrix, float sx, float sy) {
+ vkvg_matrix_t tmp;
- vkvg_matrix_init_scale (&tmp, sx, sy);
+ vkvg_matrix_init_scale(&tmp, sx, sy);
- vkvg_matrix_multiply (matrix, &tmp, matrix);
+ vkvg_matrix_multiply(matrix, &tmp, matrix);
}
-void vkvg_matrix_rotate (vkvg_matrix_t *matrix, float radians)
-{
- vkvg_matrix_t tmp;
+void vkvg_matrix_rotate(vkvg_matrix_t *matrix, float radians) {
+ vkvg_matrix_t tmp;
- vkvg_matrix_init_rotate (&tmp, radians);
+ vkvg_matrix_init_rotate(&tmp, radians);
- vkvg_matrix_multiply (matrix, &tmp, matrix);
+ vkvg_matrix_multiply(matrix, &tmp, matrix);
}
-void vkvg_matrix_multiply (vkvg_matrix_t *result, const vkvg_matrix_t *a, const vkvg_matrix_t *b)
-{
- vkvg_matrix_t r;
+void vkvg_matrix_multiply(vkvg_matrix_t *result, const vkvg_matrix_t *a, const vkvg_matrix_t *b) {
+ vkvg_matrix_t r;
- r.xx = a->xx * b->xx + a->yx * b->xy;
- r.yx = a->xx * b->yx + a->yx * b->yy;
+ r.xx = a->xx * b->xx + a->yx * b->xy;
+ r.yx = a->xx * b->yx + a->yx * b->yy;
- r.xy = a->xy * b->xx + a->yy * b->xy;
- r.yy = a->xy * b->yx + a->yy * b->yy;
+ r.xy = a->xy * b->xx + a->yy * b->xy;
+ r.yy = a->xy * b->yx + a->yy * b->yy;
- r.x0 = a->x0 * b->xx + a->y0 * b->xy + b->x0;
- r.y0 = a->x0 * b->yx + a->y0 * b->yy + b->y0;
+ r.x0 = a->x0 * b->xx + a->y0 * b->xy + b->x0;
+ r.y0 = a->x0 * b->yx + a->y0 * b->yy + b->y0;
- *result = r;
+ *result = r;
}
-void vkvg_matrix_transform_distance (const vkvg_matrix_t *matrix, float *dx, float *dy)
-{
- float new_x, new_y;
+void vkvg_matrix_transform_distance(const vkvg_matrix_t *matrix, float *dx, float *dy) {
+ float new_x, new_y;
- new_x = (matrix->xx * *dx + matrix->xy * *dy);
- new_y = (matrix->yx * *dx + matrix->yy * *dy);
+ new_x = (matrix->xx * *dx + matrix->xy * *dy);
+ new_y = (matrix->yx * *dx + matrix->yy * *dy);
- *dx = new_x;
- *dy = new_y;
+ *dx = new_x;
+ *dy = new_y;
}
-void vkvg_matrix_transform_point (const vkvg_matrix_t *matrix, float *x, float *y)
-{
- vkvg_matrix_transform_distance (matrix, x, y);
+void vkvg_matrix_transform_point(const vkvg_matrix_t *matrix, float *x, float *y) {
+ vkvg_matrix_transform_distance(matrix, x, y);
- *x += matrix->x0;
- *y += matrix->y0;
+ *x += matrix->x0;
+ *y += matrix->y0;
}
-void vkvg_matrix_get_scale (const vkvg_matrix_t *matrix, float *sx, float *sy) {
- *sx = sqrt (matrix->xx * matrix->xx + matrix->xy * matrix->xy);
- /*if (matrix->xx < 0)
- *sx = -*sx;*/
- *sy = sqrt (matrix->yx * matrix->yx + matrix->yy * matrix->yy);
- /*if (matrix->yy < 0)
- *sy = -*sy;*/
+void vkvg_matrix_get_scale(const vkvg_matrix_t *matrix, float *sx, float *sy) {
+ *sx = sqrt(matrix->xx * matrix->xx + matrix->xy * matrix->xy);
+ /*if (matrix->xx < 0)
+ *sx = -*sx;*/
+ *sy = sqrt(matrix->yx * matrix->yx + matrix->yy * matrix->yy);
+ /*if (matrix->yy < 0)
+ *sy = -*sy;*/
}
#include <stdbool.h>
#include "vkvg.h"
-
-
-
#endif
#include "vkvg_device_internal.h"
#include "vkvg_pattern.h"
-VkvgPattern vkvg_pattern_create_for_surface (VkvgSurface surf){
- VkvgPattern pat = (vkvg_pattern_t*)calloc(1, sizeof(vkvg_pattern_t));
- if (!pat)
- return (VkvgPattern)&_no_mem_status;
-
- pat->type = VKVG_PATTERN_TYPE_SURFACE;
- pat->extend = VKVG_EXTEND_NONE;
- pat->data = surf;
- pat->references = 1;
-
- vkvg_surface_reference (surf);
- if (surf->status)
- pat->status = surf->status;
-
- return pat;
-}
-vkvg_status_t vkvg_pattern_get_linear_points (VkvgPattern pat, float* x0, float* y0, float* x1, float* y1) {
- if (pat->status)
- return pat->status;
- if (pat->type != VKVG_PATTERN_TYPE_LINEAR)
- return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
-
- vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data;
-
- *x0 = grad->cp[0].x;
- *y0 = grad->cp[0].y;
- *x1 = grad->cp[0].z;
- *y1 = grad->cp[0].w;
- return VKVG_STATUS_SUCCESS;
-}
-vkvg_status_t vkvg_pattern_edit_linear (VkvgPattern pat, float x0, float y0, float x1, float y1){
- if (pat->status)
- return pat->status;
- if (pat->type != VKVG_PATTERN_TYPE_LINEAR)
- return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
-
- vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data;
-
- grad->cp[0] = (vec4){{x0}, {y0}, {x1}, {y1}};
- return VKVG_STATUS_SUCCESS;
-}
-VkvgPattern vkvg_pattern_create_linear (float x0, float y0, float x1, float y1){
- VkvgPattern pat = (vkvg_pattern_t*)calloc(1, sizeof(vkvg_pattern_t));
- if (!pat)
- return (VkvgPattern)&_no_mem_status;
- pat->type = VKVG_PATTERN_TYPE_LINEAR;
- pat->extend = VKVG_EXTEND_NONE;
-
- pat->data = (void*)calloc(1,sizeof(vkvg_gradient_t));
-
- if (pat->data) {
- vkvg_pattern_edit_linear(pat, x0, y0, x1, y1);
- pat->references = 1;
- } else
- pat->status = VKVG_STATUS_NO_MEMORY;
-
- return pat;
-}
-vkvg_status_t vkvg_pattern_edit_radial (VkvgPattern pat,
- float cx0, float cy0, float radius0,
- float cx1, float cy1, float radius1) {
- if (pat->status)
- return pat->status;
- if (pat->type != VKVG_PATTERN_TYPE_RADIAL)
- return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
-
- vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data;
-
- vec2 c0 = {cx0, cy0};
- vec2 c1 = {cx1, cy1};
-
- if (radius0 > radius1 - 1.0f)
- radius0 = radius1 - 1.0f;
- vec2 u = vec2_sub (c0, c1);
- float l = vec2_length(u);
- if (l + radius0 + 1.0f >= radius1) {
- vec2 v = vec2_div_s(u, l);
- c0 = vec2_add(c1, vec2_mult_s (v, radius1 - radius0 - 1.0f));
- }
-
- grad->cp[0] = (vec4){{c0.x}, {c0.y},{radius0},{0}};
- grad->cp[1] = (vec4){{c1.x}, {c1.y},{radius1},{0}};
- return VKVG_STATUS_SUCCESS;
-}
-VkvgPattern vkvg_pattern_create_radial (float cx0, float cy0, float radius0,
- float cx1, float cy1, float radius1){
- VkvgPattern pat = (vkvg_pattern_t*)calloc(1, sizeof(vkvg_pattern_t));
- if (!pat)
- return (VkvgPattern)&_no_mem_status;
- pat->type = VKVG_PATTERN_TYPE_RADIAL;
- pat->extend = VKVG_EXTEND_NONE;
-
- pat->data = (void*)calloc(1,sizeof(vkvg_gradient_t));
-
- if (pat->data) {
- vkvg_pattern_edit_radial (pat, cx0, cy0, radius0, cx1, cy1, radius1);
- pat->references = 1;
- } else
- pat->status = VKVG_STATUS_NO_MEMORY;
-
- return pat;
-}
-VkvgPattern vkvg_pattern_reference (VkvgPattern pat) {
- if (!pat->status)
- pat->references++;
- return pat;
-}
-uint32_t vkvg_pattern_get_reference_count (VkvgPattern pat) {
- if (pat->status)
- return 0;
- return pat->references;
-}
-vkvg_status_t vkvg_pattern_add_color_stop (VkvgPattern pat, float offset, float r, float g, float b, float a) {
- if (pat->status)
- return pat->status;
- if (pat->type == VKVG_PATTERN_TYPE_SURFACE || pat->type == VKVG_PATTERN_TYPE_SOLID)
- return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
-
- vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data;
+VkvgPattern vkvg_pattern_create_for_surface(VkvgSurface surf) {
+ VkvgPattern pat = (vkvg_pattern_t *)calloc(1, sizeof(vkvg_pattern_t));
+ if (!pat)
+ return (VkvgPattern)&_no_mem_status;
+
+ pat->type = VKVG_PATTERN_TYPE_SURFACE;
+ pat->extend = VKVG_EXTEND_NONE;
+ pat->data = surf;
+ pat->references = 1;
+
+ vkvg_surface_reference(surf);
+ if (surf->status)
+ pat->status = surf->status;
+
+ return pat;
+}
+vkvg_status_t vkvg_pattern_get_linear_points(VkvgPattern pat, float *x0, float *y0, float *x1, float *y1) {
+ if (pat->status)
+ return pat->status;
+ if (pat->type != VKVG_PATTERN_TYPE_LINEAR)
+ return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
+
+ vkvg_gradient_t *grad = (vkvg_gradient_t *)pat->data;
+
+ *x0 = grad->cp[0].x;
+ *y0 = grad->cp[0].y;
+ *x1 = grad->cp[0].z;
+ *y1 = grad->cp[0].w;
+ return VKVG_STATUS_SUCCESS;
+}
+vkvg_status_t vkvg_pattern_edit_linear(VkvgPattern pat, float x0, float y0, float x1, float y1) {
+ if (pat->status)
+ return pat->status;
+ if (pat->type != VKVG_PATTERN_TYPE_LINEAR)
+ return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
+
+ vkvg_gradient_t *grad = (vkvg_gradient_t *)pat->data;
+
+ grad->cp[0] = (vec4){{x0}, {y0}, {x1}, {y1}};
+ return VKVG_STATUS_SUCCESS;
+}
+VkvgPattern vkvg_pattern_create_linear(float x0, float y0, float x1, float y1) {
+ VkvgPattern pat = (vkvg_pattern_t *)calloc(1, sizeof(vkvg_pattern_t));
+ if (!pat)
+ return (VkvgPattern)&_no_mem_status;
+ pat->type = VKVG_PATTERN_TYPE_LINEAR;
+ pat->extend = VKVG_EXTEND_NONE;
+
+ pat->data = (void *)calloc(1, sizeof(vkvg_gradient_t));
+
+ if (pat->data) {
+ vkvg_pattern_edit_linear(pat, x0, y0, x1, y1);
+ pat->references = 1;
+ } else
+ pat->status = VKVG_STATUS_NO_MEMORY;
+
+ return pat;
+}
+vkvg_status_t vkvg_pattern_edit_radial(VkvgPattern pat, float cx0, float cy0, float radius0, float cx1, float cy1,
+ float radius1) {
+ if (pat->status)
+ return pat->status;
+ if (pat->type != VKVG_PATTERN_TYPE_RADIAL)
+ return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
+
+ vkvg_gradient_t *grad = (vkvg_gradient_t *)pat->data;
+
+ vec2 c0 = {cx0, cy0};
+ vec2 c1 = {cx1, cy1};
+
+ if (radius0 > radius1 - 1.0f)
+ radius0 = radius1 - 1.0f;
+ vec2 u = vec2_sub(c0, c1);
+ float l = vec2_length(u);
+ if (l + radius0 + 1.0f >= radius1) {
+ vec2 v = vec2_div_s(u, l);
+ c0 = vec2_add(c1, vec2_mult_s(v, radius1 - radius0 - 1.0f));
+ }
+
+ grad->cp[0] = (vec4){{c0.x}, {c0.y}, {radius0}, {0}};
+ grad->cp[1] = (vec4){{c1.x}, {c1.y}, {radius1}, {0}};
+ return VKVG_STATUS_SUCCESS;
+}
+VkvgPattern vkvg_pattern_create_radial(float cx0, float cy0, float radius0, float cx1, float cy1, float radius1) {
+ VkvgPattern pat = (vkvg_pattern_t *)calloc(1, sizeof(vkvg_pattern_t));
+ if (!pat)
+ return (VkvgPattern)&_no_mem_status;
+ pat->type = VKVG_PATTERN_TYPE_RADIAL;
+ pat->extend = VKVG_EXTEND_NONE;
+
+ pat->data = (void *)calloc(1, sizeof(vkvg_gradient_t));
+
+ if (pat->data) {
+ vkvg_pattern_edit_radial(pat, cx0, cy0, radius0, cx1, cy1, radius1);
+ pat->references = 1;
+ } else
+ pat->status = VKVG_STATUS_NO_MEMORY;
+
+ return pat;
+}
+VkvgPattern vkvg_pattern_reference(VkvgPattern pat) {
+ if (!pat->status)
+ pat->references++;
+ return pat;
+}
+uint32_t vkvg_pattern_get_reference_count(VkvgPattern pat) {
+ if (pat->status)
+ return 0;
+ return pat->references;
+}
+vkvg_status_t vkvg_pattern_add_color_stop(VkvgPattern pat, float offset, float r, float g, float b, float a) {
+ if (pat->status)
+ return pat->status;
+ if (pat->type == VKVG_PATTERN_TYPE_SURFACE || pat->type == VKVG_PATTERN_TYPE_SOLID)
+ return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
+
+ vkvg_gradient_t *grad = (vkvg_gradient_t *)pat->data;
#ifdef VKVG_PREMULT_ALPHA
- vkvg_color_t c = {a*r,a*g,a*b,a};
+ vkvg_color_t c = {a * r, a * g, a * b, a};
#else
- vkvg_color_t c = {r,g,b,a};
+ vkvg_color_t c = {r, g, b, a};
#endif
- grad->colors[grad->count] = c;
+ grad->colors[grad->count] = c;
#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
- grad->stops[grad->count] = offset;
+ grad->stops[grad->count] = offset;
#else
- grad->stops[grad->count].r = offset;
+ grad->stops[grad->count].r = offset;
#endif
- grad->count++;
-}
-void vkvg_pattern_set_extend (VkvgPattern pat, vkvg_extend_t extend){
- if (pat->status)
- return;
- pat->extend = extend;
-}
-void vkvg_pattern_set_filter (VkvgPattern pat, vkvg_filter_t filter){
- if (pat->status)
- return;
- pat->filter = filter;
-}
-
-vkvg_extend_t vkvg_pattern_get_extend (VkvgPattern pat){
- if (pat->status)
- return (vkvg_extend_t)0;
- return pat->extend;
-}
-vkvg_filter_t vkvg_pattern_get_filter (VkvgPattern pat){
- if (pat->status)
- return (vkvg_filter_t)0;
- return pat->filter;
-}
-vkvg_pattern_type_t vkvg_pattern_get_type (VkvgPattern pat){
- if (pat->status)
- return (vkvg_pattern_type_t)0;
- return pat->type;
-}
-vkvg_status_t vkvg_pattern_get_color_stop_count (VkvgPattern pat, uint32_t* count) {
- if (pat->status)
- return pat->status;
- if (pat->type == VKVG_PATTERN_TYPE_SURFACE || pat->type == VKVG_PATTERN_TYPE_SOLID)
- return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
- vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data;
- *count = grad->count;
- return VKVG_STATUS_SUCCESS;
-}
-vkvg_status_t vkvg_pattern_get_color_stop_rgba (VkvgPattern pat, uint32_t index,
- float* offset, float* r, float* g, float* b, float* a) {
- if (pat->status)
- return pat->status;
- if (pat->type == VKVG_PATTERN_TYPE_SURFACE || pat->type == VKVG_PATTERN_TYPE_SOLID)
- return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
- vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data;
- if (index >= grad->count)
- return VKVG_STATUS_INVALID_INDEX;
+ grad->count++;
+}
+void vkvg_pattern_set_extend(VkvgPattern pat, vkvg_extend_t extend) {
+ if (pat->status)
+ return;
+ pat->extend = extend;
+}
+void vkvg_pattern_set_filter(VkvgPattern pat, vkvg_filter_t filter) {
+ if (pat->status)
+ return;
+ pat->filter = filter;
+}
+
+vkvg_extend_t vkvg_pattern_get_extend(VkvgPattern pat) {
+ if (pat->status)
+ return (vkvg_extend_t)0;
+ return pat->extend;
+}
+vkvg_filter_t vkvg_pattern_get_filter(VkvgPattern pat) {
+ if (pat->status)
+ return (vkvg_filter_t)0;
+ return pat->filter;
+}
+vkvg_pattern_type_t vkvg_pattern_get_type(VkvgPattern pat) {
+ if (pat->status)
+ return (vkvg_pattern_type_t)0;
+ return pat->type;
+}
+vkvg_status_t vkvg_pattern_get_color_stop_count(VkvgPattern pat, uint32_t *count) {
+ if (pat->status)
+ return pat->status;
+ if (pat->type == VKVG_PATTERN_TYPE_SURFACE || pat->type == VKVG_PATTERN_TYPE_SOLID)
+ return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
+ vkvg_gradient_t *grad = (vkvg_gradient_t *)pat->data;
+ *count = grad->count;
+ return VKVG_STATUS_SUCCESS;
+}
+vkvg_status_t vkvg_pattern_get_color_stop_rgba(VkvgPattern pat, uint32_t index, float *offset, float *r, float *g,
+ float *b, float *a) {
+ if (pat->status)
+ return pat->status;
+ if (pat->type == VKVG_PATTERN_TYPE_SURFACE || pat->type == VKVG_PATTERN_TYPE_SOLID)
+ return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
+ vkvg_gradient_t *grad = (vkvg_gradient_t *)pat->data;
+ if (index >= grad->count)
+ return VKVG_STATUS_INVALID_INDEX;
#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
- *offset = grad->stops[index];
+ *offset = grad->stops[index];
#else
- *offset = grad->stops[index].r;
+ *offset = grad->stops[index].r;
#endif
- vkvg_color_t c = grad->colors[index];
- *r = c.r;
- *g = c.g;
- *b = c.b;
- *a = c.a;
- return VKVG_STATUS_SUCCESS;
-}
-void vkvg_pattern_set_matrix (VkvgPattern pat, const vkvg_matrix_t* matrix) {
- if (pat->status)
- return;
- pat->matrix = *matrix;
- pat->hasMatrix = true;
-}
-void vkvg_pattern_get_matrix (VkvgPattern pat, vkvg_matrix_t* matrix) {
- if (pat->status)
- return;
- if (pat->hasMatrix)
- *matrix = pat->matrix;
- else
- *matrix = VKVG_IDENTITY_MATRIX;
-}
-vkvg_status_t vkvg_pattern_status (VkvgPattern pat) {
- return pat->status;
-}
-
-void vkvg_pattern_destroy(VkvgPattern pat)
-{
- if (pat->status)
- return;
- pat->references--;
- if (pat->references > 0)
- return;
-
- if (pat->type == VKVG_PATTERN_TYPE_SURFACE) {
- VkvgSurface surf = (VkvgSurface)pat->data;
- vkvg_surface_destroy (surf);
- }else
- free (pat->data);
-
- free(pat);
+ vkvg_color_t c = grad->colors[index];
+ *r = c.r;
+ *g = c.g;
+ *b = c.b;
+ *a = c.a;
+ return VKVG_STATUS_SUCCESS;
+}
+void vkvg_pattern_set_matrix(VkvgPattern pat, const vkvg_matrix_t *matrix) {
+ if (pat->status)
+ return;
+ pat->matrix = *matrix;
+ pat->hasMatrix = true;
+}
+void vkvg_pattern_get_matrix(VkvgPattern pat, vkvg_matrix_t *matrix) {
+ if (pat->status)
+ return;
+ if (pat->hasMatrix)
+ *matrix = pat->matrix;
+ else
+ *matrix = VKVG_IDENTITY_MATRIX;
+}
+vkvg_status_t vkvg_pattern_status(VkvgPattern pat) { return pat->status; }
+
+void vkvg_pattern_destroy(VkvgPattern pat) {
+ if (pat->status)
+ return;
+ pat->references--;
+ if (pat->references > 0)
+ return;
+
+ if (pat->type == VKVG_PATTERN_TYPE_SURFACE) {
+ VkvgSurface surf = (VkvgSurface)pat->data;
+ vkvg_surface_destroy(surf);
+ } else
+ free(pat->data);
+
+ free(pat);
}
#include "vkvg_internal.h"
typedef struct _vkvg_pattern_t {
- vkvg_status_t status;
- uint32_t references;
- vkvg_pattern_type_t type;
- vkvg_extend_t extend;
- vkvg_filter_t filter;
- vkvg_matrix_t matrix;
- bool hasMatrix;
- void* data;
-}vkvg_pattern_t;
+ vkvg_status_t status;
+ uint32_t references;
+ vkvg_pattern_type_t type;
+ vkvg_extend_t extend;
+ vkvg_filter_t filter;
+ vkvg_matrix_t matrix;
+ bool hasMatrix;
+ void *data;
+} vkvg_pattern_t;
typedef struct _vkvg_gradient_t {
- vkvg_color_t colors[16];
+ vkvg_color_t colors[16];
#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
- float stops[16];
+ float stops[16];
#else
- vec4 stops[16];
+ vec4 stops[16];
#endif
- vec4 cp[2];
- uint32_t count;
-}vkvg_gradient_t;
+ vec4 cp[2];
+ uint32_t count;
+} vkvg_gradient_t;
#endif
#include "stb_image_write.h"
#include "vkh_image.h"
-#define max(x,y)
-void _transition_surf_images (VkvgSurface surf) {
- LOCK_SURFACE(surf)
- VkvgDevice dev = surf->dev;
-
- //_surface_wait_cmd (surf);
-
- vkh_cmd_begin (surf->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- VkhImage imgMs = surf->imgMS;
- if (imgMs != NULL)
- vkh_image_set_layout(surf->cmd, imgMs, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
-
- vkh_image_set_layout(surf->cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
- vkh_image_set_layout (surf->cmd, surf->stencil, dev->stencilAspectFlag,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
- vkh_cmd_end (surf->cmd);
-
- _surface_submit_cmd (surf);
-
- UNLOCK_SURFACE(surf)
+#define max(x, y)
+void _transition_surf_images(VkvgSurface surf) {
+ LOCK_SURFACE(surf)
+ VkvgDevice dev = surf->dev;
+
+ //_surface_wait_cmd (surf);
+
+ vkh_cmd_begin(surf->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ VkhImage imgMs = surf->imgMS;
+ if (imgMs != NULL)
+ vkh_image_set_layout(surf->cmd, imgMs, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+
+ vkh_image_set_layout(surf->cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+ vkh_image_set_layout(surf->cmd, surf->stencil, dev->stencilAspectFlag, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
+ vkh_cmd_end(surf->cmd);
+
+ _surface_submit_cmd(surf);
+
+ UNLOCK_SURFACE(surf)
}
-void vkvg_surface_clear (VkvgSurface surf) {
- if (surf->status)
- return;
- _clear_surface(surf, VK_IMAGE_ASPECT_STENCIL_BIT|VK_IMAGE_ASPECT_COLOR_BIT);
+void vkvg_surface_clear(VkvgSurface surf) {
+ if (surf->status)
+ return;
+ _clear_surface(surf, VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_COLOR_BIT);
}
-VkvgSurface vkvg_surface_create (VkvgDevice dev, uint32_t width, uint32_t height){
- VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT);
- if (surf->status)
- return surf;
+VkvgSurface vkvg_surface_create(VkvgDevice dev, uint32_t width, uint32_t height) {
+ VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT);
+ if (surf->status)
+ return surf;
- surf->width = MAX(1, width);
- surf->height = MAX(1, height);
- surf->newSurf = true;//used to clear all attacments on first render pass
+ surf->width = MAX(1, width);
+ surf->height = MAX(1, height);
+ surf->newSurf = true; // used to clear all attacments on first render pass
- _create_surface_images (surf);
+ _create_surface_images(surf);
- _transition_surf_images (surf);
+ _transition_surf_images(surf);
- surf->status = VKVG_STATUS_SUCCESS;
- vkvg_device_reference (surf->dev);
- return surf;
+ surf->status = VKVG_STATUS_SUCCESS;
+ vkvg_device_reference(surf->dev);
+ return surf;
}
-VkvgSurface vkvg_surface_create_for_VkhImage (VkvgDevice dev, void* vkhImg) {
- VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT);
- if (surf->status)
- return surf;
+VkvgSurface vkvg_surface_create_for_VkhImage(VkvgDevice dev, void *vkhImg) {
+ VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT);
+ if (surf->status)
+ return surf;
- if (!vkhImg) {
- surf->status = VKVG_STATUS_INVALID_IMAGE;
- return surf;
- }
+ if (!vkhImg) {
+ surf->status = VKVG_STATUS_INVALID_IMAGE;
+ return surf;
+ }
- VkhImage img = (VkhImage)vkhImg;
- surf->width = img->infos.extent.width;
- surf->height= img->infos.extent.height;
+ VkhImage img = (VkhImage)vkhImg;
+ surf->width = img->infos.extent.width;
+ surf->height = img->infos.extent.height;
- surf->img = img;
+ surf->img = img;
- vkh_image_create_sampler(img, VK_FILTER_NEAREST, VK_FILTER_NEAREST,
- VK_SAMPLER_MIPMAP_MODE_NEAREST,VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
+ vkh_image_create_sampler(img, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
- _create_surface_secondary_images (surf);
- _create_framebuffer (surf);
+ _create_surface_secondary_images(surf);
+ _create_framebuffer(surf);
- _transition_surf_images (surf);
- //_clear_surface (surf, VK_IMAGE_ASPECT_STENCIL_BIT);
+ _transition_surf_images(surf);
+ //_clear_surface (surf, VK_IMAGE_ASPECT_STENCIL_BIT);
- surf->status = VKVG_STATUS_SUCCESS;
- vkvg_device_reference (surf->dev);
- return surf;
+ surf->status = VKVG_STATUS_SUCCESS;
+ vkvg_device_reference(surf->dev);
+ return surf;
}
-//TODO: it would be better to blit in original size and create ms final image with dest surf dims
-VkvgSurface vkvg_surface_create_from_bitmap (VkvgDevice dev, unsigned char* img, uint32_t width, uint32_t height) {
- VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT);
- if (surf->status)
- return surf;
- if (!img || width <= 0 || height <= 0) {
- surf->status = VKVG_STATUS_INVALID_IMAGE;
- return surf;
- }
-
- surf->width = MAX(1, width);
- surf->height = MAX(1, height);
-
- _create_surface_images (surf);
-
- uint32_t imgSize = width * height * 4;
- VkImageSubresourceLayers imgSubResLayers = {VK_IMAGE_ASPECT_COLOR_BIT,0,0,1};
- //original format image
- VkhImage stagImg= vkh_image_create ((VkhDevice)surf->dev,VK_FORMAT_R8G8B8A8_UNORM,surf->width,surf->height,VK_IMAGE_TILING_LINEAR,
- VKH_MEMORY_USAGE_GPU_ONLY,
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT);
- //bgra bliting target
- VkhImage tmpImg = vkh_image_create ((VkhDevice)surf->dev,surf->format,surf->width,surf->height,VK_IMAGE_TILING_LINEAR,
- VKH_MEMORY_USAGE_GPU_ONLY,
- VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT);
- vkh_image_create_descriptor (tmpImg, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
- //staging buffer
- vkh_buffer_t buff = {0};
- vkh_buffer_init((VkhDevice)dev,
- VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
- VKH_MEMORY_USAGE_CPU_TO_GPU,
- imgSize, &buff, true);
-
- memcpy (vkh_buffer_get_mapped_pointer (&buff), img, imgSize);
-
- VkCommandBuffer cmd = surf->cmd;
-
- vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- vkh_image_set_layout (cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
-
-
- VkBufferImageCopy bufferCopyRegion = { .imageSubresource = imgSubResLayers,
- .imageExtent = {surf->width,surf->height,1}};
-
- vkCmdCopyBufferToImage(cmd, buff.buffer,
- vkh_image_get_vkimage (stagImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
-
- vkh_image_set_layout (cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkh_image_set_layout (cmd, tmpImg, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
-
- VkImageBlit blit = {
- .srcSubresource = imgSubResLayers,
- .srcOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
- .dstSubresource = imgSubResLayers,
- .dstOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
- };
- vkCmdBlitImage (cmd,
- vkh_image_get_vkimage (stagImg), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- vkh_image_get_vkimage (tmpImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR);
-
- vkh_image_set_layout (cmd, tmpImg, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
-
- vkh_cmd_end (cmd);
-
- _surface_submit_cmd (surf);//lock surface?
-
- vkh_buffer_reset (&buff);
- vkh_image_destroy (stagImg);
-
- surf->newSurf = false;
-
- //create tmp context with rendering pipeline to create the multisample img
- VkvgContext ctx = vkvg_create (surf);
-
-/* VkClearAttachment ca = {VK_IMAGE_ASPECT_COLOR_BIT,0, { 0.0f, 0.0f, 0.0f, 0.0f }};
- VkClearRect cr = {{{0,0},{surf->width,surf->height}},0,1};
- vkCmdClearAttachments(ctx->cmd, 1, &ca, 1, &cr);*/
-
- vec4 srcRect = {.x=0,.y=0,.width=(float)surf->width,.height=(float)surf->height};
- ctx->pushConsts.source = srcRect;
- ctx->pushConsts.fsq_patternType = (ctx->pushConsts.fsq_patternType & FULLSCREEN_BIT) + VKVG_PATTERN_TYPE_SURFACE;
-
- //_update_push_constants (ctx);
- _update_descriptor_set (ctx, tmpImg, ctx->dsSrc);
- _ensure_renderpass_is_started (ctx);
-
- vkvg_paint (ctx);
- vkvg_destroy (ctx);
-
- vkh_image_destroy (tmpImg);
-
- surf->status = VKVG_STATUS_SUCCESS;
- vkvg_device_reference (surf->dev);
- return surf;
+// TODO: it would be better to blit in original size and create ms final image with dest surf dims
+VkvgSurface vkvg_surface_create_from_bitmap(VkvgDevice dev, unsigned char *img, uint32_t width, uint32_t height) {
+ VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT);
+ if (surf->status)
+ return surf;
+ if (!img || width <= 0 || height <= 0) {
+ surf->status = VKVG_STATUS_INVALID_IMAGE;
+ return surf;
+ }
+
+ surf->width = MAX(1, width);
+ surf->height = MAX(1, height);
+
+ _create_surface_images(surf);
+
+ uint32_t imgSize = width * height * 4;
+ VkImageSubresourceLayers imgSubResLayers = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
+ // original format image
+ VkhImage stagImg = vkh_image_create((VkhDevice)surf->dev, VK_FORMAT_R8G8B8A8_UNORM, surf->width, surf->height,
+ VK_IMAGE_TILING_LINEAR, VKH_MEMORY_USAGE_GPU_ONLY,
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+ // bgra bliting target
+ VkhImage tmpImg =
+ vkh_image_create((VkhDevice)surf->dev, surf->format, surf->width, surf->height, VK_IMAGE_TILING_LINEAR,
+ VKH_MEMORY_USAGE_GPU_ONLY, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+ vkh_image_create_descriptor(tmpImg, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST,
+ VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
+ // staging buffer
+ vkh_buffer_t buff = {0};
+ vkh_buffer_init((VkhDevice)dev, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU, imgSize, &buff,
+ true);
+
+ memcpy(vkh_buffer_get_mapped_pointer(&buff), img, imgSize);
+
+ VkCommandBuffer cmd = surf->cmd;
+
+ vkh_cmd_begin(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ vkh_image_set_layout(cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ VkBufferImageCopy bufferCopyRegion = {.imageSubresource = imgSubResLayers,
+ .imageExtent = {surf->width, surf->height, 1}};
+
+ vkCmdCopyBufferToImage(cmd, buff.buffer, vkh_image_get_vkimage(stagImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
+ &bufferCopyRegion);
+
+ vkh_image_set_layout(cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout(cmd, tmpImg, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ VkImageBlit blit = {
+ .srcSubresource = imgSubResLayers,
+ .srcOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
+ .dstSubresource = imgSubResLayers,
+ .dstOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
+ };
+ vkCmdBlitImage(cmd, vkh_image_get_vkimage(stagImg), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vkh_image_get_vkimage(tmpImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR);
+
+ vkh_image_set_layout(cmd, tmpImg, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+
+ vkh_cmd_end(cmd);
+
+ _surface_submit_cmd(surf); // lock surface?
+
+ vkh_buffer_reset(&buff);
+ vkh_image_destroy(stagImg);
+
+ surf->newSurf = false;
+
+ // create tmp context with rendering pipeline to create the multisample img
+ VkvgContext ctx = vkvg_create(surf);
+
+ /* VkClearAttachment ca = {VK_IMAGE_ASPECT_COLOR_BIT,0, { 0.0f, 0.0f, 0.0f, 0.0f }};
+ VkClearRect cr = {{{0,0},{surf->width,surf->height}},0,1};
+ vkCmdClearAttachments(ctx->cmd, 1, &ca, 1, &cr);*/
+
+ vec4 srcRect = {.x = 0, .y = 0, .width = (float)surf->width, .height = (float)surf->height};
+ ctx->pushConsts.source = srcRect;
+ ctx->pushConsts.fsq_patternType = (ctx->pushConsts.fsq_patternType & FULLSCREEN_BIT) + VKVG_PATTERN_TYPE_SURFACE;
+
+ //_update_push_constants (ctx);
+ _update_descriptor_set(ctx, tmpImg, ctx->dsSrc);
+ _ensure_renderpass_is_started(ctx);
+
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
+
+ vkh_image_destroy(tmpImg);
+
+ surf->status = VKVG_STATUS_SUCCESS;
+ vkvg_device_reference(surf->dev);
+ return surf;
}
-VkvgSurface vkvg_surface_create_from_image (VkvgDevice dev, const char* filePath) {
- int w = 0,
- h = 0,
- channels = 0;
- unsigned char *img = stbi_load(filePath, &w, &h, &channels, 4);//force 4 components per pixel
- if (!img){
- LOG(VKVG_LOG_ERR, "Could not load texture from %s, %s\n", filePath, stbi_failure_reason());
- return (VkvgSurface)&_no_mem_status;
- }
+VkvgSurface vkvg_surface_create_from_image(VkvgDevice dev, const char *filePath) {
+ int w = 0, h = 0, channels = 0;
+ unsigned char *img = stbi_load(filePath, &w, &h, &channels, 4); // force 4 components per pixel
+ if (!img) {
+ LOG(VKVG_LOG_ERR, "Could not load texture from %s, %s\n", filePath, stbi_failure_reason());
+ return (VkvgSurface)&_no_mem_status;
+ }
- VkvgSurface surf = vkvg_surface_create_from_bitmap(dev, img, (uint32_t)w, (uint32_t)h);
+ VkvgSurface surf = vkvg_surface_create_from_bitmap(dev, img, (uint32_t)w, (uint32_t)h);
- stbi_image_free (img);
+ stbi_image_free(img);
- return surf;
+ return surf;
}
-void vkvg_surface_destroy(VkvgSurface surf)
-{
- if (surf->status)
- return;
+void vkvg_surface_destroy(VkvgSurface surf) {
+ if (surf->status)
+ return;
- LOCK_SURFACE(surf)
- surf->references--;
- if (surf->references > 0) {
- UNLOCK_SURFACE(surf)
- return;
- }
- UNLOCK_SURFACE(surf)
+ LOCK_SURFACE(surf)
+ surf->references--;
+ if (surf->references > 0) {
+ UNLOCK_SURFACE(surf)
+ return;
+ }
+ UNLOCK_SURFACE(surf)
- vkDestroyCommandPool(surf->dev->vkDev, surf->cmdPool, NULL);
- vkDestroyFramebuffer(surf->dev->vkDev, surf->fb, NULL);
+ vkDestroyCommandPool(surf->dev->vkDev, surf->cmdPool, NULL);
+ vkDestroyFramebuffer(surf->dev->vkDev, surf->fb, NULL);
- if (!surf->img->imported)
- vkh_image_destroy(surf->img);
+ if (!surf->img->imported)
+ vkh_image_destroy(surf->img);
- vkh_image_destroy(surf->imgMS);
- vkh_image_destroy(surf->stencil);
+ vkh_image_destroy(surf->imgMS);
+ vkh_image_destroy(surf->stencil);
- if (surf->dev->threadAware)
- mtx_destroy (&surf->mutex);
+ if (surf->dev->threadAware)
+ mtx_destroy(&surf->mutex);
#if VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- vkDestroySemaphore (surf->dev->vkDev, surf->timeline, NULL);
+ vkDestroySemaphore(surf->dev->vkDev, surf->timeline, NULL);
#else
- vkDestroyFence (surf->dev->vkDev, surf->flushFence, NULL);
+ vkDestroyFence(surf->dev->vkDev, surf->flushFence, NULL);
#endif
- vkvg_device_destroy (surf->dev);
- free(surf);
+ vkvg_device_destroy(surf->dev);
+ free(surf);
}
-VkvgSurface vkvg_surface_reference (VkvgSurface surf) {
- if (!surf->status) {
- LOCK_SURFACE(surf)
- surf->references++;
- UNLOCK_SURFACE(surf)
- }
- return surf;
+VkvgSurface vkvg_surface_reference(VkvgSurface surf) {
+ if (!surf->status) {
+ LOCK_SURFACE(surf)
+ surf->references++;
+ UNLOCK_SURFACE(surf)
+ }
+ return surf;
}
-uint32_t vkvg_surface_get_reference_count (VkvgSurface surf) {
- if (surf->status)
- return 0;
- return surf->references;
+uint32_t vkvg_surface_get_reference_count(VkvgSurface surf) {
+ if (surf->status)
+ return 0;
+ return surf->references;
}
-VkImage vkvg_surface_get_vk_image(VkvgSurface surf)
-{
- if (surf->status)
- return NULL;
- if (surf->dev->deferredResolve)
- _explicit_ms_resolve(surf);
- return vkh_image_get_vkimage (surf->img);
+VkImage vkvg_surface_get_vk_image(VkvgSurface surf) {
+ if (surf->status)
+ return NULL;
+ if (surf->dev->deferredResolve)
+ _explicit_ms_resolve(surf);
+ return vkh_image_get_vkimage(surf->img);
}
-void vkvg_surface_resolve (VkvgSurface surf){
- if (surf->status || !surf->dev->deferredResolve)
- return;
- _explicit_ms_resolve(surf);
+void vkvg_surface_resolve(VkvgSurface surf) {
+ if (surf->status || !surf->dev->deferredResolve)
+ return;
+ _explicit_ms_resolve(surf);
}
-VkFormat vkvg_surface_get_vk_format(VkvgSurface surf)
-{
- if (surf->status)
- return VK_FORMAT_UNDEFINED;
- return surf->format;
+VkFormat vkvg_surface_get_vk_format(VkvgSurface surf) {
+ if (surf->status)
+ return VK_FORMAT_UNDEFINED;
+ return surf->format;
}
-uint32_t vkvg_surface_get_width (VkvgSurface surf) {
- if (surf->status)
- return 0;
- return surf->width;
+uint32_t vkvg_surface_get_width(VkvgSurface surf) {
+ if (surf->status)
+ return 0;
+ return surf->width;
}
-uint32_t vkvg_surface_get_height (VkvgSurface surf) {
- if (surf->status)
- return 0;
- return surf->height;
+uint32_t vkvg_surface_get_height(VkvgSurface surf) {
+ if (surf->status)
+ return 0;
+ return surf->height;
}
-vkvg_status_t vkvg_surface_write_to_png (VkvgSurface surf, const char* path){
- if (surf->status) {
- LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_png failed, invalid status: %d\n", surf->status);
- return VKVG_STATUS_INVALID_STATUS;
- }
- if (surf->dev->status) {
- LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_png failed, invalid device status: %d\n", surf->dev->status);
- return VKVG_STATUS_INVALID_STATUS;
- }
- if (surf->dev->pngStagFormat == VK_FORMAT_UNDEFINED) {
- LOG(VKVG_LOG_ERR, "no suitable image format for png write\n");
- return VKVG_STATUS_INVALID_FORMAT;
- }
- if (!path) {
- LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_png failed, null path\n");
- return VKVG_STATUS_WRITE_ERROR;
- }
- LOCK_SURFACE(surf)
- VkImageSubresourceLayers imgSubResLayers = {VK_IMAGE_ASPECT_COLOR_BIT,0,0,1};
- VkvgDevice dev = surf->dev;
-
- //RGBA to blit to, surf img is bgra
- VkhImage stagImg;
-
- if (dev->pngStagTiling == VK_IMAGE_TILING_LINEAR)
- stagImg = vkh_image_create ((VkhDevice)surf->dev, dev->pngStagFormat, surf->width, surf->height, dev->pngStagTiling,
- VKH_MEMORY_USAGE_GPU_TO_CPU,
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT);
- else
- stagImg = vkh_image_create ((VkhDevice)surf->dev, dev->pngStagFormat, surf->width,surf->height, dev->pngStagTiling,
- VKH_MEMORY_USAGE_GPU_ONLY,
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT);
-
- VkCommandBuffer cmd = surf->cmd;
- vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- vkh_image_set_layout (cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkh_image_set_layout (cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
-
- VkImageBlit blit = {
- .srcSubresource = imgSubResLayers,
- .srcOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
- .dstSubresource = imgSubResLayers,
- .dstOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
- };
- vkCmdBlitImage (cmd,
- vkh_image_get_vkimage (surf->img), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- vkh_image_get_vkimage (stagImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST);
-
- vkh_cmd_end (cmd);
-
- _surface_submit_cmd (surf);
-
- VkhImage stagImgLinear = stagImg;
-
- if (dev->pngStagTiling == VK_IMAGE_TILING_OPTIMAL) {
- stagImgLinear = vkh_image_create ((VkhDevice)surf->dev, dev->pngStagFormat, surf->width, surf->height, VK_IMAGE_TILING_LINEAR,
- VKH_MEMORY_USAGE_GPU_TO_CPU,
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT);
- VkImageCopy cpy = {
- .srcSubresource = imgSubResLayers,
- .srcOffset = {0},
- .dstSubresource = imgSubResLayers,
- .dstOffset = {0},
- .extent = {(int32_t)surf->width, (int32_t)surf->height, 1}
- };
-
- vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- vkh_image_set_layout (cmd, stagImgLinear, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkh_image_set_layout (cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkCmdCopyImage(cmd,
- vkh_image_get_vkimage (stagImg), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- vkh_image_get_vkimage (stagImgLinear), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cpy);
-
- vkh_cmd_end (cmd);
-
- _surface_submit_cmd (surf);
-
- vkh_image_destroy (stagImg);
- }
-
- void* img = vkh_image_map (stagImgLinear);
-
- uint64_t stride = vkh_image_get_stride(stagImgLinear);
-
- stbi_write_png (path, (int32_t)surf->width, (int32_t)surf->height, 4, img, (int32_t)stride);
-
- vkh_image_unmap (stagImgLinear);
- vkh_image_destroy (stagImgLinear);
-
- UNLOCK_SURFACE(surf)
- return VKVG_STATUS_SUCCESS;
+vkvg_status_t vkvg_surface_write_to_png(VkvgSurface surf, const char *path) {
+ if (surf->status) {
+ LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_png failed, invalid status: %d\n", surf->status);
+ return VKVG_STATUS_INVALID_STATUS;
+ }
+ if (surf->dev->status) {
+ LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_png failed, invalid device status: %d\n", surf->dev->status);
+ return VKVG_STATUS_INVALID_STATUS;
+ }
+ if (surf->dev->pngStagFormat == VK_FORMAT_UNDEFINED) {
+ LOG(VKVG_LOG_ERR, "no suitable image format for png write\n");
+ return VKVG_STATUS_INVALID_FORMAT;
+ }
+ if (!path) {
+ LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_png failed, null path\n");
+ return VKVG_STATUS_WRITE_ERROR;
+ }
+ LOCK_SURFACE(surf)
+ VkImageSubresourceLayers imgSubResLayers = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
+ VkvgDevice dev = surf->dev;
+
+ // RGBA to blit to, surf img is bgra
+ VkhImage stagImg;
+
+ if (dev->pngStagTiling == VK_IMAGE_TILING_LINEAR)
+ stagImg = vkh_image_create((VkhDevice)surf->dev, dev->pngStagFormat, surf->width, surf->height,
+ dev->pngStagTiling, VKH_MEMORY_USAGE_GPU_TO_CPU,
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+ else
+ stagImg = vkh_image_create((VkhDevice)surf->dev, dev->pngStagFormat, surf->width, surf->height,
+ dev->pngStagTiling, VKH_MEMORY_USAGE_GPU_ONLY,
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+
+ VkCommandBuffer cmd = surf->cmd;
+ vkh_cmd_begin(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ vkh_image_set_layout(cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout(cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ VkImageBlit blit = {
+ .srcSubresource = imgSubResLayers,
+ .srcOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
+ .dstSubresource = imgSubResLayers,
+ .dstOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
+ };
+ vkCmdBlitImage(cmd, vkh_image_get_vkimage(surf->img), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vkh_image_get_vkimage(stagImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST);
+
+ vkh_cmd_end(cmd);
+
+ _surface_submit_cmd(surf);
+
+ VkhImage stagImgLinear = stagImg;
+
+ if (dev->pngStagTiling == VK_IMAGE_TILING_OPTIMAL) {
+ stagImgLinear = vkh_image_create((VkhDevice)surf->dev, dev->pngStagFormat, surf->width, surf->height,
+ VK_IMAGE_TILING_LINEAR, VKH_MEMORY_USAGE_GPU_TO_CPU,
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+ VkImageCopy cpy = {.srcSubresource = imgSubResLayers,
+ .srcOffset = {0},
+ .dstSubresource = imgSubResLayers,
+ .dstOffset = {0},
+ .extent = {(int32_t)surf->width, (int32_t)surf->height, 1}};
+
+ vkh_cmd_begin(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ vkh_image_set_layout(cmd, stagImgLinear, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout(cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkCmdCopyImage(cmd, vkh_image_get_vkimage(stagImg), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vkh_image_get_vkimage(stagImgLinear), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cpy);
+
+ vkh_cmd_end(cmd);
+
+ _surface_submit_cmd(surf);
+
+ vkh_image_destroy(stagImg);
+ }
+
+ void *img = vkh_image_map(stagImgLinear);
+
+ uint64_t stride = vkh_image_get_stride(stagImgLinear);
+
+ stbi_write_png(path, (int32_t)surf->width, (int32_t)surf->height, 4, img, (int32_t)stride);
+
+ vkh_image_unmap(stagImgLinear);
+ vkh_image_destroy(stagImgLinear);
+
+ UNLOCK_SURFACE(surf)
+ return VKVG_STATUS_SUCCESS;
}
-vkvg_status_t vkvg_surface_write_to_memory (VkvgSurface surf, unsigned char* const bitmap){
- if (surf->status) {
- LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_memory failed, invalid status: %d\n", surf->status);
- return VKVG_STATUS_INVALID_STATUS;
- }
- if (!bitmap) {
- LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_memory failed, null path\n");
- return VKVG_STATUS_INVALID_IMAGE;
- }
-
- LOCK_SURFACE(surf)
-
- VkImageSubresourceLayers imgSubResLayers = {VK_IMAGE_ASPECT_COLOR_BIT,0,0,1};
- VkvgDevice dev = surf->dev;
-
- //RGBA to blit to, surf img is bgra
- VkhImage stagImg= vkh_image_create ((VkhDevice)surf->dev,VK_FORMAT_B8G8R8A8_UNORM ,surf->width,surf->height,VK_IMAGE_TILING_LINEAR,
- VKH_MEMORY_USAGE_GPU_TO_CPU,
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT);
-
- VkCommandBuffer cmd = surf->cmd;
-
- vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- vkh_image_set_layout (cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkh_image_set_layout (cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
-
- VkImageBlit blit = {
- .srcSubresource = imgSubResLayers,
- .srcOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
- .dstSubresource = imgSubResLayers,
- .dstOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
- };
- vkCmdBlitImage (cmd,
- vkh_image_get_vkimage (surf->img), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- vkh_image_get_vkimage (stagImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST);
-
- vkh_cmd_end (cmd);
-
- _surface_submit_cmd (surf);
-
- uint64_t stride = vkh_image_get_stride(stagImg);
- uint32_t dest_stride = surf->width * 4;
-
- char* img = vkh_image_map (stagImg);
- char* row = (char*)bitmap;
- for (uint32_t y = 0; y < surf->height; y++) {
- memcpy(row, img, dest_stride);
- row += dest_stride;
- img += stride;
- }
-
- vkh_image_unmap (stagImg);
- vkh_image_destroy (stagImg);
-
- UNLOCK_SURFACE(surf)
-
- return VKVG_STATUS_SUCCESS;
+vkvg_status_t vkvg_surface_write_to_memory(VkvgSurface surf, unsigned char *const bitmap) {
+ if (surf->status) {
+ LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_memory failed, invalid status: %d\n", surf->status);
+ return VKVG_STATUS_INVALID_STATUS;
+ }
+ if (!bitmap) {
+ LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_memory failed, null path\n");
+ return VKVG_STATUS_INVALID_IMAGE;
+ }
+
+ LOCK_SURFACE(surf)
+
+ VkImageSubresourceLayers imgSubResLayers = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
+ VkvgDevice dev = surf->dev;
+
+ // RGBA to blit to, surf img is bgra
+ VkhImage stagImg = vkh_image_create((VkhDevice)surf->dev, VK_FORMAT_B8G8R8A8_UNORM, surf->width, surf->height,
+ VK_IMAGE_TILING_LINEAR, VKH_MEMORY_USAGE_GPU_TO_CPU,
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+
+ VkCommandBuffer cmd = surf->cmd;
+
+ vkh_cmd_begin(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ vkh_image_set_layout(cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout(cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ VkImageBlit blit = {
+ .srcSubresource = imgSubResLayers,
+ .srcOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
+ .dstSubresource = imgSubResLayers,
+ .dstOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1},
+ };
+ vkCmdBlitImage(cmd, vkh_image_get_vkimage(surf->img), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vkh_image_get_vkimage(stagImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST);
+
+ vkh_cmd_end(cmd);
+
+ _surface_submit_cmd(surf);
+
+ uint64_t stride = vkh_image_get_stride(stagImg);
+ uint32_t dest_stride = surf->width * 4;
+
+ char *img = vkh_image_map(stagImg);
+ char *row = (char *)bitmap;
+ for (uint32_t y = 0; y < surf->height; y++) {
+ memcpy(row, img, dest_stride);
+ row += dest_stride;
+ img += stride;
+ }
+
+ vkh_image_unmap(stagImg);
+ vkh_image_destroy(stagImg);
+
+ UNLOCK_SURFACE(surf)
+
+ return VKVG_STATUS_SUCCESS;
}
#include "vkh_image.h"
#include "vkh_queue.h"
-void _explicit_ms_resolve (VkvgSurface surf){
- LOCK_SURFACE (surf)
-
- VkCommandBuffer cmd = surf->cmd;
-
- vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- vkh_image_set_layout (cmd, surf->imgMS, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkh_image_set_layout (cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
-
- VkImageResolve re = {
- .extent = {surf->width, surf->height,1},
- .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT,0,0,1},
- .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT,0,0,1}
- };
-
- vkCmdResolveImage(cmd,
- vkh_image_get_vkimage (surf->imgMS), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- vkh_image_get_vkimage (surf->img) ,VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1,&re);
- vkh_image_set_layout (cmd, surf->imgMS, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
- vkh_cmd_end (cmd);
-
- _surface_submit_cmd (surf);
-
- UNLOCK_SURFACE (surf)
+void _explicit_ms_resolve(VkvgSurface surf) {
+ LOCK_SURFACE(surf)
+
+ VkCommandBuffer cmd = surf->cmd;
+
+ vkh_cmd_begin(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ vkh_image_set_layout(cmd, surf->imgMS, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout(cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ VkImageResolve re = {.extent = {surf->width, surf->height, 1},
+ .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
+ .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}};
+
+ vkCmdResolveImage(cmd, vkh_image_get_vkimage(surf->imgMS), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vkh_image_get_vkimage(surf->img), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &re);
+ vkh_image_set_layout(cmd, surf->imgMS, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+ vkh_cmd_end(cmd);
+
+ _surface_submit_cmd(surf);
+
+ UNLOCK_SURFACE(surf)
}
-void _clear_surface (VkvgSurface surf, VkImageAspectFlags aspect)
-{
- LOCK_SURFACE (surf)
+void _clear_surface(VkvgSurface surf, VkImageAspectFlags aspect) {
+ LOCK_SURFACE(surf)
- VkCommandBuffer cmd = surf->cmd;
+ VkCommandBuffer cmd = surf->cmd;
- vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ vkh_cmd_begin(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) {
- VkClearColorValue cclr = {{0,0,0,0}};
- VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,1};
+ if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) {
+ VkClearColorValue cclr = {{0, 0, 0, 0}};
+ VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
- VkhImage img = surf->imgMS;
- if (surf->dev->samples == VK_SAMPLE_COUNT_1_BIT)
- img = surf->img;
+ VkhImage img = surf->imgMS;
+ if (surf->dev->samples == VK_SAMPLE_COUNT_1_BIT)
+ img = surf->img;
- vkh_image_set_layout (cmd, img, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout(cmd, img, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkCmdClearColorImage(cmd, vkh_image_get_vkimage (img),
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &cclr, 1, &range);
+ vkCmdClearColorImage(cmd, vkh_image_get_vkimage(img), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &cclr, 1, &range);
- vkh_image_set_layout (cmd, img, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
- }
- if (aspect & VK_IMAGE_ASPECT_STENCIL_BIT) {
- VkClearDepthStencilValue clr = {0,0};
- VkImageSubresourceRange range = {VK_IMAGE_ASPECT_STENCIL_BIT,0,1,0,1};
+ vkh_image_set_layout(cmd, img, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+ }
+ if (aspect & VK_IMAGE_ASPECT_STENCIL_BIT) {
+ VkClearDepthStencilValue clr = {0, 0};
+ VkImageSubresourceRange range = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1};
- vkh_image_set_layout (cmd, surf->stencil, VK_IMAGE_ASPECT_STENCIL_BIT,
- VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout(cmd, surf->stencil, VK_IMAGE_ASPECT_STENCIL_BIT,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- vkCmdClearDepthStencilImage (cmd, vkh_image_get_vkimage (surf->stencil),
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,&clr,1,&range);
+ vkCmdClearDepthStencilImage(cmd, vkh_image_get_vkimage(surf->stencil), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ &clr, 1, &range);
- vkh_image_set_layout (cmd, surf->stencil, VK_IMAGE_ASPECT_STENCIL_BIT,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
- }
- vkh_cmd_end (cmd);
+ vkh_image_set_layout(cmd, surf->stencil, VK_IMAGE_ASPECT_STENCIL_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
+ }
+ vkh_cmd_end(cmd);
- _surface_submit_cmd (surf);
+ _surface_submit_cmd(surf);
- UNLOCK_SURFACE (surf)
+ UNLOCK_SURFACE(surf)
}
-void _create_surface_main_image (VkvgSurface surf){
- surf->img = vkh_image_create((VkhDevice)surf->dev,surf->format,surf->width,surf->height,surf->dev->supportedTiling,VKH_MEMORY_USAGE_GPU_ONLY,
- VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT);
- vkh_image_create_descriptor(surf->img, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_image_set_name(surf->img, "SURF main color");
- vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(surf->img), "SURF main color VIEW");
- vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(surf->img), "SURF main color SAMPLER");
+void _create_surface_main_image(VkvgSurface surf) {
+ surf->img = vkh_image_create((VkhDevice)surf->dev, surf->format, surf->width, surf->height,
+ surf->dev->supportedTiling, VKH_MEMORY_USAGE_GPU_ONLY,
+ VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+ vkh_image_create_descriptor(surf->img, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST,
+ VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_image_set_name(surf->img, "SURF main color");
+ vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(surf->img),
+ "SURF main color VIEW");
+ vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(surf->img),
+ "SURF main color SAMPLER");
#endif
}
-//create multisample color img if sample count > 1 and the stencil buffer multisampled or not
-void _create_surface_secondary_images (VkvgSurface surf) {
- if (surf->dev->samples > VK_SAMPLE_COUNT_1_BIT){
- surf->imgMS = vkh_image_ms_create((VkhDevice)surf->dev,surf->format,surf->dev->samples,surf->width,surf->height,VKH_MEMORY_USAGE_GPU_ONLY,
- VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
- vkh_image_create_descriptor(surf->imgMS, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST,
- VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_image_set_name(surf->imgMS, "SURF MS color IMG");
- vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(surf->imgMS), "SURF MS color VIEW");
- vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(surf->imgMS), "SURF MS color SAMPLER");
+// create multisample color img if sample count > 1 and the stencil buffer multisampled or not
+void _create_surface_secondary_images(VkvgSurface surf) {
+ if (surf->dev->samples > VK_SAMPLE_COUNT_1_BIT) {
+ surf->imgMS = vkh_image_ms_create((VkhDevice)surf->dev, surf->format, surf->dev->samples, surf->width,
+ surf->height, VKH_MEMORY_USAGE_GPU_ONLY,
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+ vkh_image_create_descriptor(surf->imgMS, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST,
+ VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_image_set_name(surf->imgMS, "SURF MS color IMG");
+ vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_IMAGE_VIEW,
+ (uint64_t)vkh_image_get_view(surf->imgMS), "SURF MS color VIEW");
+ vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_SAMPLER,
+ (uint64_t)vkh_image_get_sampler(surf->imgMS), "SURF MS color SAMPLER");
#endif
- }
- surf->stencil = vkh_image_ms_create((VkhDevice)surf->dev,surf->dev->stencilFormat,surf->dev->samples,surf->width,surf->height,VKH_MEMORY_USAGE_GPU_ONLY, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
- vkh_image_create_descriptor(surf->stencil, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_STENCIL_BIT, VK_FILTER_NEAREST,
- VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_image_set_name(surf->stencil, "SURF stencil");
- vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(surf->stencil), "SURF stencil VIEW");
- vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(surf->stencil), "SURF stencil SAMPLER");
+ }
+ surf->stencil = vkh_image_ms_create((VkhDevice)surf->dev, surf->dev->stencilFormat, surf->dev->samples, surf->width,
+ surf->height, VKH_MEMORY_USAGE_GPU_ONLY,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+ vkh_image_create_descriptor(surf->stencil, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_STENCIL_BIT, VK_FILTER_NEAREST,
+ VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_image_set_name(surf->stencil, "SURF stencil");
+ vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_IMAGE_VIEW,
+ (uint64_t)vkh_image_get_view(surf->stencil), "SURF stencil VIEW");
+ vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_SAMPLER,
+ (uint64_t)vkh_image_get_sampler(surf->stencil), "SURF stencil SAMPLER");
#endif
}
-void _create_framebuffer (VkvgSurface surf) {
- VkImageView attachments[] = {
- vkh_image_get_view (surf->img),
- vkh_image_get_view (surf->stencil),
- vkh_image_get_view (surf->imgMS),
- };
- VkFramebufferCreateInfo frameBufferCreateInfo = { .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
- .renderPass = surf->dev->renderPass,
- .attachmentCount = 3,
- .pAttachments = attachments,
- .width = surf->width,
- .height = surf->height,
- .layers = 1 };
- if (surf->dev->samples == VK_SAMPLE_COUNT_1_BIT)
- frameBufferCreateInfo.attachmentCount = 2;
- else if (surf->dev->deferredResolve) {
- attachments[0] = attachments[2];
- frameBufferCreateInfo.attachmentCount = 2;
- }
- VK_CHECK_RESULT(vkCreateFramebuffer(surf->dev->vkDev, &frameBufferCreateInfo, NULL, &surf->fb));
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_FRAMEBUFFER, (uint64_t)surf->fb, "SURF FB");
+void _create_framebuffer(VkvgSurface surf) {
+ VkImageView attachments[] = {
+ vkh_image_get_view(surf->img),
+ vkh_image_get_view(surf->stencil),
+ vkh_image_get_view(surf->imgMS),
+ };
+ VkFramebufferCreateInfo frameBufferCreateInfo = {.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ .renderPass = surf->dev->renderPass,
+ .attachmentCount = 3,
+ .pAttachments = attachments,
+ .width = surf->width,
+ .height = surf->height,
+ .layers = 1};
+ if (surf->dev->samples == VK_SAMPLE_COUNT_1_BIT)
+ frameBufferCreateInfo.attachmentCount = 2;
+ else if (surf->dev->deferredResolve) {
+ attachments[0] = attachments[2];
+ frameBufferCreateInfo.attachmentCount = 2;
+ }
+ VK_CHECK_RESULT(vkCreateFramebuffer(surf->dev->vkDev, &frameBufferCreateInfo, NULL, &surf->fb));
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_FRAMEBUFFER, (uint64_t)surf->fb, "SURF FB");
#endif
}
-void _create_surface_images (VkvgSurface surf) {
+void _create_surface_images(VkvgSurface surf) {
- _create_surface_main_image (surf);
- _create_surface_secondary_images(surf);
- _create_framebuffer (surf);
+ _create_surface_main_image(surf);
+ _create_surface_secondary_images(surf);
+ _create_framebuffer(surf);
#if defined(DEBUG) && defined(ENABLE_VALIDATION)
- vkh_image_set_name(surf->img, "surfImg");
- vkh_image_set_name(surf->imgMS, "surfImgMS");
- vkh_image_set_name(surf->stencil, "surfStencil");
+ vkh_image_set_name(surf->img, "surfImg");
+ vkh_image_set_name(surf->imgMS, "surfImgMS");
+ vkh_image_set_name(surf->stencil, "surfStencil");
#endif
}
-VkvgSurface _create_surface (VkvgDevice dev, VkFormat format) {
- VkvgSurface surf = (vkvg_surface*)calloc(1,sizeof(vkvg_surface));
- if (!surf)
- return (VkvgSurface)&_no_mem_status;
-
- surf->references = 1;
- if (dev->status != VKVG_STATUS_SUCCESS) {
- surf->status = VKVG_STATUS_DEVICE_ERROR;
- return surf;
- }
- surf->dev = dev;
- surf->format = format;
- if (dev->threadAware)
- mtx_init (&surf->mutex, mtx_plain);
- surf->cmdPool = vkh_cmd_pool_create ((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
- vkh_cmd_buffs_create((VkhDevice)dev, surf->cmdPool,VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1, &surf->cmd);
+VkvgSurface _create_surface(VkvgDevice dev, VkFormat format) {
+ VkvgSurface surf = (vkvg_surface *)calloc(1, sizeof(vkvg_surface));
+ if (!surf)
+ return (VkvgSurface)&_no_mem_status;
+
+ surf->references = 1;
+ if (dev->status != VKVG_STATUS_SUCCESS) {
+ surf->status = VKVG_STATUS_DEVICE_ERROR;
+ return surf;
+ }
+ surf->dev = dev;
+ surf->format = format;
+ if (dev->threadAware)
+ mtx_init(&surf->mutex, mtx_plain);
+ surf->cmdPool =
+ vkh_cmd_pool_create((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
+ vkh_cmd_buffs_create((VkhDevice)dev, surf->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1, &surf->cmd);
#if VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- surf->timeline = vkh_timeline_create ((VkhDevice)dev, 0);
+ surf->timeline = vkh_timeline_create((VkhDevice)dev, 0);
#else
- surf->flushFence = vkh_fence_create ((VkhDevice)dev);
+ surf->flushFence = vkh_fence_create((VkhDevice)dev);
#endif
#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)surf->cmd, "vkvgSurfCmd");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)surf->cmd, "vkvgSurfCmd");
#endif
- return surf;
+ return surf;
}
-//if fence sync, surf mutex must be locked.
+// if fence sync, surf mutex must be locked.
/*bool _surface_wait_cmd (VkvgSurface surf) {
- LOG(VKVG_LOG_INFO, "SURF: _surface__wait_flush_fence\n");
+ LOG(VKVG_LOG_INFO, "SURF: _surface__wait_flush_fence\n");
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- if (vkh_timeline_wait ((VkhDevice)surf->dev, surf->timeline, surf->timelineStep) == VK_SUCCESS)
- return true;
+ if (vkh_timeline_wait ((VkhDevice)surf->dev, surf->timeline, surf->timelineStep) == VK_SUCCESS)
+ return true;
#else
- if (WaitForFences (surf->dev->vkDev, 1, &surf->flushFence, VK_TRUE, VKVG_FENCE_TIMEOUT) == VK_SUCCESS) {
- ResetFences (surf->dev->vkDev, 1, &surf->flushFence);
- return true;
- }
+ if (WaitForFences (surf->dev->vkDev, 1, &surf->flushFence, VK_TRUE, VKVG_FENCE_TIMEOUT) == VK_SUCCESS) {
+ ResetFences (surf->dev->vkDev, 1, &surf->flushFence);
+ return true;
+ }
#endif
- LOG(VKVG_LOG_DEBUG, "CTX: _wait_flush_fence timeout\n");
- surf->status = VKVG_STATUS_TIMEOUT;
- return false;
+ LOG(VKVG_LOG_DEBUG, "CTX: _wait_flush_fence timeout\n");
+ surf->status = VKVG_STATUS_TIMEOUT;
+ return false;
}*/
-//surface mutex must be locked to call this method, locking to guard also the surf->cmd local buffer usage.
-void _surface_submit_cmd (VkvgSurface surf) {
- VkvgDevice dev = surf->dev;
+// surface mutex must be locked to call this method, locking to guard also the surf->cmd local buffer usage.
+void _surface_submit_cmd(VkvgSurface surf) {
+ VkvgDevice dev = surf->dev;
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- LOCK_DEVICE
- vkh_cmd_submit_timelined (dev->gQueue, &surf->cmd, surf->timeline, surf->timelineStep, surf->timelineStep+1);
- surf->timelineStep++;
- UNLOCK_DEVICE
- vkh_timeline_wait ((VkhDevice)dev, surf->timeline, surf->timelineStep);
+ LOCK_DEVICE
+ vkh_cmd_submit_timelined(dev->gQueue, &surf->cmd, surf->timeline, surf->timelineStep, surf->timelineStep + 1);
+ surf->timelineStep++;
+ UNLOCK_DEVICE
+ vkh_timeline_wait((VkhDevice)dev, surf->timeline, surf->timelineStep);
#else
- LOCK_DEVICE
- vkh_cmd_submit (surf->dev->gQueue, &surf->cmd, surf->flushFence);
- UNLOCK_DEVICE
- WaitForFences (surf->dev->vkDev, 1, &surf->flushFence, VK_TRUE, VKVG_FENCE_TIMEOUT);
- ResetFences (surf->dev->vkDev, 1, &surf->flushFence);
+ LOCK_DEVICE
+ vkh_cmd_submit(surf->dev->gQueue, &surf->cmd, surf->flushFence);
+ UNLOCK_DEVICE
+ WaitForFences(surf->dev->vkDev, 1, &surf->flushFence, VK_TRUE, VKVG_FENCE_TIMEOUT);
+ ResetFences(surf->dev->vkDev, 1, &surf->flushFence);
#endif
}
#include "vkh.h"
typedef struct _vkvg_surface_t {
- vkvg_status_t status; /**< Current status of surface, affected by last operation */
- uint32_t references;
- VkvgDevice dev;
- uint32_t width;
- uint32_t height;
- VkFormat format;
- VkFramebuffer fb;
- VkhImage img;
- VkhImage imgMS;
- VkhImage stencil;
- VkCommandPool cmdPool; //local pools ensure thread safety
- VkCommandBuffer cmd; //surface local command buffer.
- bool newSurf;
- mtx_t mutex;
+ vkvg_status_t status; /**< Current status of surface, affected by last operation */
+ uint32_t references;
+ VkvgDevice dev;
+ uint32_t width;
+ uint32_t height;
+ VkFormat format;
+ VkFramebuffer fb;
+ VkhImage img;
+ VkhImage imgMS;
+ VkhImage stencil;
+ VkCommandPool cmdPool; // local pools ensure thread safety
+ VkCommandBuffer cmd; // surface local command buffer.
+ bool newSurf;
+ mtx_t mutex;
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
- VkSemaphore timeline; /**< Timeline semaphore */
- uint64_t timelineStep;
+ VkSemaphore timeline; /**< Timeline semaphore */
+ uint64_t timelineStep;
#else
- VkFence flushFence; //unsignaled idle.
+ VkFence flushFence; // unsignaled idle.
#endif
-}vkvg_surface;
+} vkvg_surface;
-#define LOCK_SURFACE(surf) \
- if (surf->dev->threadAware)\
- mtx_lock (&surf->mutex);
-#define UNLOCK_SURFACE(surf) \
- if (surf->dev->threadAware)\
- mtx_unlock (&surf->mutex);
+#define LOCK_SURFACE(surf) \
+ if (surf->dev->threadAware) \
+ mtx_lock(&surf->mutex);
+#define UNLOCK_SURFACE(surf) \
+ if (surf->dev->threadAware) \
+ mtx_unlock(&surf->mutex);
-void _explicit_ms_resolve (VkvgSurface surf);
-void _clear_surface (VkvgSurface surf, VkImageAspectFlags aspect);
-void _create_surface_main_image (VkvgSurface surf);
-void _create_surface_secondary_images (VkvgSurface surf);
-void _create_framebuffer (VkvgSurface surf);
-void _create_surface_images (VkvgSurface surf);
-VkvgSurface _create_surface (VkvgDevice dev, VkFormat format);
+void _explicit_ms_resolve(VkvgSurface surf);
+void _clear_surface(VkvgSurface surf, VkImageAspectFlags aspect);
+void _create_surface_main_image(VkvgSurface surf);
+void _create_surface_secondary_images(VkvgSurface surf);
+void _create_framebuffer(VkvgSurface surf);
+void _create_surface_images(VkvgSurface surf);
+VkvgSurface _create_surface(VkvgDevice dev, VkFormat format);
-void _surface_submit_cmd (VkvgSurface surf);
-//bool _surface_wait_cmd (VkvgSurface surf);
+void _surface_submit_cmd(VkvgSurface surf);
+// bool _surface_wait_cmd (VkvgSurface surf);
#endif
#include "test.h"
-void test_name(){
- VkvgContext ctx = vkvg_create(surf);
+void test_name() {
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- PERFORM_TEST (test_name, argc, argv);
- return 0;
+ PERFORM_TEST(test_name, argc, argv);
+ return 0;
}
#include "test.h"
-void draw_growing_circles (VkvgContext ctx, float y, int count) {
- float x = 2;
- for (int i=1; i<count; i++) {
- x += 0.5f*i;
- //vkvg_set_source_rgb (ctx, 1,0,1);
- vkvg_arc(ctx, x + 2, y, 0.5f * i, 0, M_PIF*1.5f);
- //vkvg_set_source_rgb (ctx, 0,1,1);
- //vkvg_arc_negative(ctx, x + 2, y, 0.5 * i, M_PI/2,0);
- x += 0.5f*i + 5;
- }
+void draw_growing_circles(VkvgContext ctx, float y, int count) {
+ float x = 2;
+ for (int i = 1; i < count; i++) {
+ x += 0.5f * i;
+ // vkvg_set_source_rgb (ctx, 1,0,1);
+ vkvg_arc(ctx, x + 2, y, 0.5f * i, 0, M_PIF * 1.5f);
+ // vkvg_set_source_rgb (ctx, 0,1,1);
+ // vkvg_arc_negative(ctx, x + 2, y, 0.5 * i, M_PI/2,0);
+ x += 0.5f * i + 5;
+ }
}
void scaled_up() {
- VkvgContext ctx = vkvg_create(surf);
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgb (ctx, 1,1,1);
- vkvg_paint(ctx);
- vkvg_set_source_rgb (ctx, 0,0,0);
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgb(ctx, 0, 0, 0);
- vkvg_scale(ctx,10,10);
- vkvg_arc(ctx, 20, 20, 2.0f, 0, M_PIF/2.f);
- vkvg_stroke(ctx);
+ vkvg_scale(ctx, 10, 10);
+ vkvg_arc(ctx, 20, 20, 2.0f, 0, M_PIF / 2.f);
+ vkvg_stroke(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
void sizes() {
- VkvgContext ctx = vkvg_create(surf);
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgb (ctx, 1,1,1);
- vkvg_paint(ctx);
- vkvg_set_source_rgb (ctx, 0,0,0);
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgb(ctx, 0, 0, 0);
- draw_growing_circles (ctx, 100, 40);
- vkvg_stroke(ctx);
+ draw_growing_circles(ctx, 100, 40);
+ vkvg_stroke(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
-void test(){
- VkvgContext ctx = vkvg_create(surf);
-
- vkvg_set_source_rgb (ctx, 1,1,1);
- vkvg_paint(ctx);
- vkvg_set_source_rgb (ctx, 0,0,0);
-
- vkvg_set_source_rgb (ctx, 1,0,1);
- vkvg_set_line_width(ctx, 5.0);
- vkvg_arc(ctx, 100, 100, 20, 0, M_PIF/2);
- vkvg_stroke(ctx);
-
- vkvg_set_source_rgb (ctx, 0,1,1);
- vkvg_arc_negative(ctx, 100, 100, 20, 0, M_PIF/2);
- vkvg_stroke(ctx);
-
- vkvg_set_source_rgb (ctx, 1,0,1);
- vkvg_arc(ctx, 100, 200, 20, M_PIF/2, 0);
- vkvg_stroke(ctx);
-
- vkvg_set_source_rgb (ctx, 0,1,1);
- vkvg_arc_negative(ctx, 100, 200, 20, M_PIF/2, 0);
- vkvg_stroke(ctx);
-
- vkvg_set_source_rgb (ctx, 0,0,1);
- vkvg_set_line_width(ctx, 10.0);
- vkvg_arc(ctx, 350, 100, 40, 0, M_PIF*2);
- vkvg_stroke(ctx);
-
- vkvg_set_source_rgb (ctx, 0,1,0);
- vkvg_set_line_width(ctx, 1.0);
- vkvg_arc(ctx, 150, 100, 3.5, 0, M_PIF*2);
- vkvg_stroke(ctx);
- vkvg_arc(ctx, 200, 200, 10, 0, M_PIF*2);
- vkvg_fill(ctx);
-
- vkvg_set_source_rgb (ctx, 1,0,0);
- vkvg_scale(ctx,3,3);
- vkvg_arc(ctx, 150, 100, 3.5, 0, M_PIF*2);
- vkvg_stroke(ctx);
- vkvg_arc(ctx, 200, 200, 10, 0, M_PIF*2);
- vkvg_fill(ctx);
-
- vkvg_destroy(ctx);
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
+
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgb(ctx, 0, 0, 0);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 1);
+ vkvg_set_line_width(ctx, 5.0);
+ vkvg_arc(ctx, 100, 100, 20, 0, M_PIF / 2);
+ vkvg_stroke(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 1, 1);
+ vkvg_arc_negative(ctx, 100, 100, 20, 0, M_PIF / 2);
+ vkvg_stroke(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 1);
+ vkvg_arc(ctx, 100, 200, 20, M_PIF / 2, 0);
+ vkvg_stroke(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 1, 1);
+ vkvg_arc_negative(ctx, 100, 200, 20, M_PIF / 2, 0);
+ vkvg_stroke(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_set_line_width(ctx, 10.0);
+ vkvg_arc(ctx, 350, 100, 40, 0, M_PIF * 2);
+ vkvg_stroke(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_set_line_width(ctx, 1.0);
+ vkvg_arc(ctx, 150, 100, 3.5, 0, M_PIF * 2);
+ vkvg_stroke(ctx);
+ vkvg_arc(ctx, 200, 200, 10, 0, M_PIF * 2);
+ vkvg_fill(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_scale(ctx, 3, 3);
+ vkvg_arc(ctx, 150, 100, 3.5, 0, M_PIF * 2);
+ vkvg_stroke(ctx);
+ vkvg_arc(ctx, 200, 200, 10, 0, M_PIF * 2);
+ vkvg_fill(ctx);
+
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (sizes, argc, argv);
- PERFORM_TEST (scaled_up, argc, argv);
- PERFORM_TEST (test, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(sizes, argc, argv);
+ PERFORM_TEST(scaled_up, argc, argv);
+ PERFORM_TEST(test, argc, argv);
+ return 0;
}
#include "test.h"
#include "vectors.h"
-vkvg_fill_rule_t fillrule = VKVG_FILL_RULE_NON_ZERO;
-static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
-float lineWidth = 10.0f;
-vkvg_line_join_t lineJoin = VKVG_LINE_JOIN_MITER;
-vkvg_line_cap_t lineCap = VKVG_LINE_CAP_BUTT;
-bool isClosed = false, isFilled = false;
-
-int ptsCount = 4;
-int initPtsCount = 4;
-vec2 pts[] = {
- {150,150},
- {500,340},
- {470,150},
- {160,350},
+vkvg_fill_rule_t fillrule = VKVG_FILL_RULE_NON_ZERO;
+static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
+float lineWidth = 10.0f;
+vkvg_line_join_t lineJoin = VKVG_LINE_JOIN_MITER;
+vkvg_line_cap_t lineCap = VKVG_LINE_CAP_BUTT;
+bool isClosed = false, isFilled = false;
+
+int ptsCount = 4;
+int initPtsCount = 4;
+vec2 pts[] = {
+ {150, 150},
+ {500, 340},
+ {470, 150},
+ {160, 350},
};
/*vec2 pts[] = {
- {150,150},
- {250,150},
- {100,150},
- {150,200},
+ {150,150},
+ {250,150},
+ {100,150},
+ {150,200},
};*/
-int hoverPt = -1;
-double hoverPointSize = 7,
- pointSize = 5;
+int hoverPt = -1;
+double hoverPointSize = 7, pointSize = 5;
#ifdef VKVG_WIRED_DEBUG
vkvg_wired_debug_mode _wired_debug = vkvg_wired_debug_mode_normal;
#endif
-void draw (){
+void draw() {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
#ifdef VKVG_WIRED_DEBUG
- vkvg_wired_debug = _wired_debug;
+ vkvg_wired_debug = _wired_debug;
#endif
- vkvg_set_line_width (ctx,lineWidth);
- vkvg_set_line_join (ctx, lineJoin);
- vkvg_set_line_cap (ctx, lineCap);
+ vkvg_set_line_width(ctx, lineWidth);
+ vkvg_set_line_join(ctx, lineJoin);
+ vkvg_set_line_cap(ctx, lineCap);
- vkvg_move_to(ctx,pts[0].x,pts[0].y);
- vkvg_curve_to(ctx, pts[1].x,pts[1].y, pts[2].x,pts[2].y, pts[3].x,pts[3].y);
+ vkvg_move_to(ctx, pts[0].x, pts[0].y);
+ vkvg_curve_to(ctx, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
- if (isClosed)
- vkvg_close_path(ctx);
+ if (isClosed)
+ vkvg_close_path(ctx);
- if (isFilled) {
- vkvg_set_source_rgba(ctx,0.4,0.6,0.4,1);
- vkvg_fill_preserve (ctx);
- }
+ if (isFilled) {
+ vkvg_set_source_rgba(ctx, 0.4, 0.6, 0.4, 1);
+ vkvg_fill_preserve(ctx);
+ }
- vkvg_set_source_rgba(ctx,1,0,0,0.3f);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.3f);
- vkvg_stroke (ctx);
- vkvg_flush (ctx);
+ vkvg_stroke(ctx);
+ vkvg_flush(ctx);
#ifdef VKVG_WIRED_DEBUG
- vkvg_wired_debug = vkvg_wired_debug_mode_normal;
+ vkvg_wired_debug = vkvg_wired_debug_mode_normal;
#endif
- vkvg_set_line_width(ctx, 1);
- vkvg_set_source_rgba(ctx,0.5,0.5,0.5,0.6);
- for (int i=0; i<ptsCount; i++) {
-
- if (i == hoverPt) {
- vkvg_arc (ctx, pts[i].x, pts[i].y, hoverPointSize, 0, M_PIF*2);
- vkvg_set_source_rgba (ctx, 0.5, 0.5, 1.0, 0.6);
- vkvg_fill_preserve (ctx);
- vkvg_set_source_rgba (ctx, 0.5 ,0.5 ,0.5 ,0.6);
- } else {
- vkvg_arc (ctx, pts[i].x, pts[i].y, pointSize, 0, M_PIF*2);
- vkvg_fill_preserve (ctx);
- }
- vkvg_stroke (ctx);
-
-
- }
-
- if (hoverPt>=0) {
- vkvg_stroke_preserve(ctx);
- vkvg_set_dash(ctx, NULL, 0, 0);
- vkvg_set_line_width(ctx,2);
- vkvg_set_source_rgba(ctx,0,0,0,1);
- vkvg_stroke(ctx);
- vkvg_set_source_rgba(ctx,0.5f,0.5f,1.0f,0.7f);
- vkvg_arc (ctx, pts[hoverPt].x, pts[hoverPt].y, pointSize, 0, M_PIF*2);
- vkvg_fill_preserve(ctx);
- vkvg_stroke(ctx);
- } else
- vkvg_stroke(ctx);
-
- //draw_v(ctx, 200, 20, VKVG_LINE_JOIN_BEVEL);
- //draw_v(ctx, 300, 80, VKVG_LINE_JOIN_ROUND);
- vkvg_destroy(ctx);
+ vkvg_set_line_width(ctx, 1);
+ vkvg_set_source_rgba(ctx, 0.5, 0.5, 0.5, 0.6);
+ for (int i = 0; i < ptsCount; i++) {
+
+ if (i == hoverPt) {
+ vkvg_arc(ctx, pts[i].x, pts[i].y, hoverPointSize, 0, M_PIF * 2);
+ vkvg_set_source_rgba(ctx, 0.5, 0.5, 1.0, 0.6);
+ vkvg_fill_preserve(ctx);
+ vkvg_set_source_rgba(ctx, 0.5, 0.5, 0.5, 0.6);
+ } else {
+ vkvg_arc(ctx, pts[i].x, pts[i].y, pointSize, 0, M_PIF * 2);
+ vkvg_fill_preserve(ctx);
+ }
+ vkvg_stroke(ctx);
+ }
+
+ if (hoverPt >= 0) {
+ vkvg_stroke_preserve(ctx);
+ vkvg_set_dash(ctx, NULL, 0, 0);
+ vkvg_set_line_width(ctx, 2);
+ vkvg_set_source_rgba(ctx, 0, 0, 0, 1);
+ vkvg_stroke(ctx);
+ vkvg_set_source_rgba(ctx, 0.5f, 0.5f, 1.0f, 0.7f);
+ vkvg_arc(ctx, pts[hoverPt].x, pts[hoverPt].y, pointSize, 0, M_PIF * 2);
+ vkvg_fill_preserve(ctx);
+ vkvg_stroke(ctx);
+ } else
+ vkvg_stroke(ctx);
+
+ // draw_v(ctx, 200, 20, VKVG_LINE_JOIN_BEVEL);
+ // draw_v(ctx, 300, 80, VKVG_LINE_JOIN_ROUND);
+ vkvg_destroy(ctx);
}
-static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
- if (action == GLFW_RELEASE)
- return;
- switch (key) {
- case GLFW_KEY_ESCAPE :
- glfwSetWindowShouldClose(window, GLFW_TRUE);
- break;
- case GLFW_KEY_W :
- isClosed ^= true;
- break;
- case GLFW_KEY_F :
- isFilled ^= true;
- break;
- case GLFW_KEY_J :
- lineJoin++;
- if (lineJoin > 2)
- lineJoin = 0;
- break;
- case GLFW_KEY_C :
- lineCap++;
- if (lineCap > 2)
- lineCap = 0;
- break;
- case GLFW_KEY_KP_ADD :
- lineWidth++;
- break;
- case GLFW_KEY_KP_SUBTRACT :
- if (lineWidth > 1)
- lineWidth--;
- break;
+static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+ if (action == GLFW_RELEASE)
+ return;
+ switch (key) {
+ case GLFW_KEY_ESCAPE:
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+ break;
+ case GLFW_KEY_W:
+ isClosed ^= true;
+ break;
+ case GLFW_KEY_F:
+ isFilled ^= true;
+ break;
+ case GLFW_KEY_J:
+ lineJoin++;
+ if (lineJoin > 2)
+ lineJoin = 0;
+ break;
+ case GLFW_KEY_C:
+ lineCap++;
+ if (lineCap > 2)
+ lineCap = 0;
+ break;
+ case GLFW_KEY_KP_ADD:
+ lineWidth++;
+ break;
+ case GLFW_KEY_KP_SUBTRACT:
+ if (lineWidth > 1)
+ lineWidth--;
+ break;
#ifdef VKVG_WIRED_DEBUG
- case GLFW_KEY_F1:
- _wired_debug ^= (1U << 0);
- break;
- case GLFW_KEY_F2:
- _wired_debug ^= (1U << 1);
- break;
- case GLFW_KEY_F3:
- _wired_debug ^= (1U << 2);
- break;
+ case GLFW_KEY_F1:
+ _wired_debug ^= (1U << 0);
+ break;
+ case GLFW_KEY_F2:
+ _wired_debug ^= (1U << 1);
+ break;
+ case GLFW_KEY_F3:
+ _wired_debug ^= (1U << 2);
+ break;
#endif
- }
+ }
}
-static void mouse_move_callback(GLFWwindow* window, double x, double y){
- if (mouseDown) {
- if (hoverPt < 0)
- return;
- pts[hoverPt].x = x;
- pts[hoverPt].y = y;
- } else {
- for (int i=0; i<ptsCount; i++) {
- if (x > pts[i].x - hoverPointSize &&
- x < pts[i].x + hoverPointSize &&
- y > pts[i].y - hoverPointSize &&
- y < pts[i].y + hoverPointSize) {
- hoverPt = i;
- return;
- }
- }
- hoverPt = -1;
- }
+static void mouse_move_callback(GLFWwindow *window, double x, double y) {
+ if (mouseDown) {
+ if (hoverPt < 0)
+ return;
+ pts[hoverPt].x = x;
+ pts[hoverPt].y = y;
+ } else {
+ for (int i = 0; i < ptsCount; i++) {
+ if (x > pts[i].x - hoverPointSize && x < pts[i].x + hoverPointSize && y > pts[i].y - hoverPointSize &&
+ y < pts[i].y + hoverPointSize) {
+ hoverPt = i;
+ return;
+ }
+ }
+ hoverPt = -1;
+ }
}
-static void scroll_callback(GLFWwindow* window, double x, double y){
- if (y<0.f)
- zoom *= 0.5f;
- else
- zoom *= 2.0f;
+static void scroll_callback(GLFWwindow *window, double x, double y) {
+ if (y < 0.f)
+ zoom *= 0.5f;
+ else
+ zoom *= 2.0f;
}
-static void mouse_button_callback(GLFWwindow* window, int but, int state, int modif){
- if (but != GLFW_MOUSE_BUTTON_1)
- return;
- if (state == GLFW_TRUE)
- mouseDown = true;
- else
- mouseDown = false;
+static void mouse_button_callback(GLFWwindow *window, int but, int state, int modif) {
+ if (but != GLFW_MOUSE_BUTTON_1)
+ return;
+ if (state == GLFW_TRUE)
+ mouseDown = true;
+ else
+ mouseDown = false;
}
+int main(int argc, char *argv[]) {
+ _parse_args(argc, argv);
+ VkEngine e;
+ e = vkengine_create(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
-int main(int argc, char* argv[]) {
+ VkhPresenter r = e->renderer;
+ vkengine_set_key_callback(e, key_callback);
+ vkengine_set_mouse_but_callback(e, mouse_button_callback);
+ vkengine_set_cursor_pos_callback(e, mouse_move_callback);
+ vkengine_set_scroll_callback(e, scroll_callback);
- _parse_args (argc, argv);
- VkEngine e;
- e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
+ vkvg_device_create_info_t info = {samples, false, vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0};
+ device = vkvg_device_create(&info);
- VkhPresenter r = e->renderer;
- vkengine_set_key_callback (e, key_callback);
- vkengine_set_mouse_but_callback(e, mouse_button_callback);
- vkengine_set_cursor_pos_callback(e, mouse_move_callback);
- vkengine_set_scroll_callback(e, scroll_callback);
+ surf = vkvg_surface_create(device, test_width, test_height);
- vkvg_device_create_info_t info = {
- samples,
- false,
- vkh_app_get_inst(e->app),
- r->dev->phy,
- r->dev->dev,
- r->qFam,
- 0
- };
- device = vkvg_device_create(&info);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
- surf = vkvg_surface_create(device, test_width, test_height);
+ while (!vkengine_should_close(e)) {
+ glfwPollEvents();
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ draw();
- while (!vkengine_should_close (e)) {
- glfwPollEvents();
+ if (!vkh_presenter_draw(r)) {
+ vkh_presenter_get_size(r, &test_width, &test_height);
+ vkvg_surface_destroy(surf);
+ surf = vkvg_surface_create(device, test_width, test_height);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ vkDeviceWaitIdle(r->dev->dev);
+ continue;
+ }
+ }
+ vkDeviceWaitIdle(e->dev->dev);
- draw ();
+ vkvg_surface_destroy(surf);
- if (!vkh_presenter_draw (r)){
- vkh_presenter_get_size (r, &test_width, &test_height);
- vkvg_surface_destroy (surf);
- surf = vkvg_surface_create(device, test_width, test_height);
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
- vkDeviceWaitIdle(r->dev->dev);
- continue;
- }
- }
- vkDeviceWaitIdle(e->dev->dev);
+ vkvg_device_destroy(device);
- vkvg_surface_destroy (surf);
+ vkengine_destroy(e);
- vkvg_device_destroy (device);
-
- vkengine_destroy (e);
-
- return 0;
+ return 0;
}
#include "test.h"
-void draw_growing_circles (VkvgContext ctx, float y, int count) {
- float x = 2;
- for (int i=1; i<count; i++) {
- x += 0.5f*i;
- vkvg_arc(ctx, x + 2, y, 0.5f * i, 0, M_PIF*2.f);
- x += 0.5f*i + 5;
- }
+void draw_growing_circles(VkvgContext ctx, float y, int count) {
+ float x = 2;
+ for (int i = 1; i < count; i++) {
+ x += 0.5f * i;
+ vkvg_arc(ctx, x + 2, y, 0.5f * i, 0, M_PIF * 2.f);
+ x += 0.5f * i + 5;
+ }
}
void scaled_up() {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
- vkvg_set_source_rgb (ctx, 1,1,1);
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
- vkvg_scale(ctx,100,100);
- vkvg_arc(ctx, 2, 2, 0.5f, 0, M_PIF*2);
- vkvg_stroke(ctx);
+ vkvg_scale(ctx, 100, 100);
+ vkvg_arc(ctx, 2, 2, 0.5f, 0, M_PIF * 2);
+ vkvg_stroke(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
-void fill_and_stroke () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
- vkvg_set_source_rgba (ctx, 0,0.1f,0.8f, 0.5f);
- vkvg_set_line_width(ctx,10);
+void fill_and_stroke() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+ vkvg_set_source_rgba(ctx, 0, 0.1f, 0.8f, 0.5f);
+ vkvg_set_line_width(ctx, 10);
- vkvg_arc(ctx, 300, 300, 150.f, 0, M_PIF*2);
- vkvg_fill_preserve(ctx);
- vkvg_stroke(ctx);
+ vkvg_arc(ctx, 300, 300, 150.f, 0, M_PIF * 2);
+ vkvg_fill_preserve(ctx);
+ vkvg_stroke(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
void sizes() {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
- vkvg_set_source_rgb (ctx, 1,1,1);
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
- draw_growing_circles (ctx, 100, 40);
- vkvg_fill (ctx);
+ draw_growing_circles(ctx, 100, 40);
+ vkvg_fill(ctx);
- draw_growing_circles (ctx, 200, 40);
- vkvg_stroke(ctx);
+ draw_growing_circles(ctx, 200, 40);
+ vkvg_stroke(ctx);
- vkvg_set_source_rgba (ctx, 0,0,1,0.4F);
- draw_growing_circles (ctx, 300, 40);
- vkvg_fill_preserve (ctx);
- vkvg_set_line_width(ctx,5);
- vkvg_stroke(ctx);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 0.4F);
+ draw_growing_circles(ctx, 300, 40);
+ vkvg_fill_preserve(ctx);
+ vkvg_set_line_width(ctx, 5);
+ vkvg_stroke(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (fill_and_stroke, argc, argv);
- PERFORM_TEST (sizes, argc, argv);
- PERFORM_TEST (scaled_up, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(fill_and_stroke, argc, argv);
+ PERFORM_TEST(sizes, argc, argv);
+ PERFORM_TEST(scaled_up, argc, argv);
+ return 0;
}
#include "test.h"
-void clipped_paint_ec () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_paint(ctx);
- vkvg_set_source_rgb(ctx,0,1,0);
- vkvg_rectangle(ctx, 100,100,300,200);
- vkvg_clip(ctx);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
+void clipped_paint_ec() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_clip(ctx);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
}
-void clipped_paint_eo () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_paint(ctx);
- vkvg_set_source_rgb(ctx,0,1,0);
- vkvg_rectangle(ctx, 100,100,300,200);
- vkvg_clip(ctx);
- vkvg_paint(ctx);
-
- vkvg_destroy(ctx);
+void clipped_paint_eo() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_clip(ctx);
+ vkvg_paint(ctx);
+
+ vkvg_destroy(ctx);
}
-void clipped_paint2_ec () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_paint(ctx);
- vkvg_set_source_rgb(ctx,0,1,0);
- vkvg_rectangle(ctx, 100,100,300,200);
- vkvg_clip(ctx);
- vkvg_paint(ctx);
-
- vkvg_reset_clip(ctx);
- vkvg_rectangle(ctx, 200,200,300,200);
- vkvg_set_source_rgb(ctx,0,0,1);
- vkvg_paint(ctx);
-
- vkvg_destroy(ctx);
+void clipped_paint2_ec() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_clip(ctx);
+ vkvg_paint(ctx);
+
+ vkvg_reset_clip(ctx);
+ vkvg_rectangle(ctx, 200, 200, 300, 200);
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_paint(ctx);
+
+ vkvg_destroy(ctx);
}
-void clipped_paint2_eo () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_paint(ctx);
- vkvg_set_source_rgb(ctx,0,1,0);
- vkvg_rectangle(ctx, 100,100,300,200);
- vkvg_clip(ctx);
- vkvg_paint(ctx);
- vkvg_reset_clip(ctx);
- vkvg_rectangle(ctx, 200,200,300,200);
- vkvg_set_source_rgb(ctx,0,0,1);
- vkvg_paint(ctx);
-
- vkvg_destroy(ctx);
+void clipped_paint2_eo() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_clip(ctx);
+ vkvg_paint(ctx);
+ vkvg_reset_clip(ctx);
+ vkvg_rectangle(ctx, 200, 200, 300, 200);
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_paint(ctx);
+
+ vkvg_destroy(ctx);
}
-void clipped_transformed_ec () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_paint(ctx);
- vkvg_rotate(ctx,0.2f);
- vkvg_set_source_rgb(ctx,0,1,0);
- vkvg_rectangle(ctx, 100,100,300,200);
- vkvg_clip(ctx);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
+void clipped_transformed_ec() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_rotate(ctx, 0.2f);
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_clip(ctx);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
}
-void clip_transformed_ec () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_paint(ctx);
- vkvg_rotate(ctx,0.1f);
- vkvg_set_source_rgb(ctx,0,1,0);
- vkvg_rectangle(ctx, 100,100,300,200);
- vkvg_clip(ctx);
- vkvg_paint(ctx);
- vkvg_translate (ctx,200,100);
- vkvg_set_source_rgb(ctx,0,0,1);
- vkvg_paint(ctx);
-
- vkvg_destroy(ctx);
+void clip_transformed_ec() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_rotate(ctx, 0.1f);
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_clip(ctx);
+ vkvg_paint(ctx);
+ vkvg_translate(ctx, 200, 100);
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_paint(ctx);
+
+ vkvg_destroy(ctx);
}
-void clipped_transformed_eo () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_paint(ctx);
- vkvg_rotate(ctx,0.2f);
- vkvg_set_source_rgb(ctx,0,1,0);
- vkvg_rectangle(ctx, 100,100,300,200);
- vkvg_clip(ctx);
- vkvg_paint(ctx);
-
- vkvg_destroy(ctx);
+void clipped_transformed_eo() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_rotate(ctx, 0.2f);
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_clip(ctx);
+ vkvg_paint(ctx);
+
+ vkvg_destroy(ctx);
}
-void test_clip(){
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_move_to(ctx,10,10);
- vkvg_line_to(ctx,400,150);
- vkvg_line_to(ctx,900,10);
- vkvg_line_to(ctx,700,450);
- vkvg_line_to(ctx,900,750);
- vkvg_line_to(ctx,500,650);
- vkvg_line_to(ctx,100,800);
- vkvg_line_to(ctx,150,400);
- vkvg_clip_preserve(ctx);
- vkvg_set_operator(ctx, VKVG_OPERATOR_CLEAR);
- vkvg_fill_preserve(ctx);
- vkvg_clip(ctx);
- vkvg_set_operator(ctx, VKVG_OPERATOR_OVER);
-
- vkvg_set_source_rgb(ctx,1,0,0);
- //vkvg_set_line_width(ctx,10);
- //vkvg_stroke(ctx);
- vkvg_paint(ctx);
-
- vkvg_destroy(ctx);
+void test_clip() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+ vkvg_move_to(ctx, 10, 10);
+ vkvg_line_to(ctx, 400, 150);
+ vkvg_line_to(ctx, 900, 10);
+ vkvg_line_to(ctx, 700, 450);
+ vkvg_line_to(ctx, 900, 750);
+ vkvg_line_to(ctx, 500, 650);
+ vkvg_line_to(ctx, 100, 800);
+ vkvg_line_to(ctx, 150, 400);
+ vkvg_clip_preserve(ctx);
+ vkvg_set_operator(ctx, VKVG_OPERATOR_CLEAR);
+ vkvg_fill_preserve(ctx);
+ vkvg_clip(ctx);
+ vkvg_set_operator(ctx, VKVG_OPERATOR_OVER);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ // vkvg_set_line_width(ctx,10);
+ // vkvg_stroke(ctx);
+ vkvg_paint(ctx);
+
+ vkvg_destroy(ctx);
}
-void test_clip2(){
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
- vkvg_rectangle(ctx, 50,50,500,500);
- vkvg_clip(ctx);
-
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_paint(ctx);
-
- vkvg_save(ctx);
- vkvg_rectangle(ctx, 100,100,350,350);
- vkvg_clip(ctx);
- vkvg_save(ctx);
-
- vkvg_set_source_rgb(ctx,1,1,0);
- vkvg_paint(ctx);
-
- vkvg_rectangle(ctx, 200,200,200,200);
- vkvg_clip(ctx);
-
- vkvg_set_source_rgb(ctx,0,1,0);
- vkvg_paint(ctx);
-
- vkvg_restore(ctx);
-
- vkvg_rectangle(ctx, 350,350,420,420);
- vkvg_set_source_rgb(ctx,0,0,1);
- vkvg_fill(ctx);
-
- vkvg_restore(ctx);
-
- //vkvg_clip(ctx);
- //
- /*vkvg_clip_preserve(ctx);
- vkvg_set_operator(ctx, VKVG_OPERATOR_CLEAR);
- vkvg_fill_preserve(ctx);*/
- //vkvg_clip(ctx);
- //vkvg_set_operator(ctx, VKVG_OPERATOR_OVER);
- /*vkvg_rectangle(ctx, 200,200,220,220);
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_paint(ctx);*/
-
-
-
-
- vkvg_destroy(ctx);
+void test_clip2() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
+ vkvg_rectangle(ctx, 50, 50, 500, 500);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+
+ vkvg_save(ctx);
+ vkvg_rectangle(ctx, 100, 100, 350, 350);
+ vkvg_clip(ctx);
+ vkvg_save(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 1, 0);
+ vkvg_paint(ctx);
+
+ vkvg_rectangle(ctx, 200, 200, 200, 200);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_paint(ctx);
+
+ vkvg_restore(ctx);
+
+ vkvg_rectangle(ctx, 350, 350, 420, 420);
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_fill(ctx);
+
+ vkvg_restore(ctx);
+
+ // vkvg_clip(ctx);
+ //
+ /*vkvg_clip_preserve(ctx);
+ vkvg_set_operator(ctx, VKVG_OPERATOR_CLEAR);
+ vkvg_fill_preserve(ctx);*/
+ // vkvg_clip(ctx);
+ // vkvg_set_operator(ctx, VKVG_OPERATOR_OVER);
+ /*vkvg_rectangle(ctx, 200,200,220,220);
+ vkvg_set_source_rgb(ctx,1,0,0);
+ vkvg_paint(ctx);*/
+
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (clip_transformed_ec, argc, argv);
- PERFORM_TEST (clipped_paint_ec, argc, argv);
- PERFORM_TEST (clipped_paint_eo, argc, argv);
- PERFORM_TEST (clipped_transformed_ec, argc, argv);
- PERFORM_TEST (clipped_transformed_eo, argc, argv);
- PERFORM_TEST (clipped_paint2_ec, argc, argv);
- PERFORM_TEST (clipped_paint2_eo, argc, argv);
- PERFORM_TEST (test_clip, argc, argv);
- PERFORM_TEST (test_clip2, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(clip_transformed_ec, argc, argv);
+ PERFORM_TEST(clipped_paint_ec, argc, argv);
+ PERFORM_TEST(clipped_paint_eo, argc, argv);
+ PERFORM_TEST(clipped_transformed_ec, argc, argv);
+ PERFORM_TEST(clipped_transformed_eo, argc, argv);
+ PERFORM_TEST(clipped_paint2_ec, argc, argv);
+ PERFORM_TEST(clipped_paint2_eo, argc, argv);
+ PERFORM_TEST(test_clip, argc, argv);
+ PERFORM_TEST(test_clip2, argc, argv);
+ return 0;
}
#include "test.h"
-void test(){
- VkvgContext ctx = vkvg_create(surf);
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgba(ctx,0.7f,0.7f,0.7f,1);
- vkvg_paint(ctx);
+ vkvg_set_source_rgba(ctx, 0.7f, 0.7f, 0.7f, 1);
+ vkvg_paint(ctx);
- vkvg_set_source_rgba(ctx,0,1,0,1);
- vkvg_set_line_width(ctx,10);
+ vkvg_set_source_rgba(ctx, 0, 1, 0, 1);
+ vkvg_set_line_width(ctx, 10);
- vkvg_move_to(ctx,100,100);
- vkvg_line_to(ctx,100,200);
- vkvg_line_to(ctx,100,300);
- vkvg_stroke(ctx);
+ vkvg_move_to(ctx, 100, 100);
+ vkvg_line_to(ctx, 100, 200);
+ vkvg_line_to(ctx, 100, 300);
+ vkvg_stroke(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (test, argc, argv);
+ no_test_size = true;
+ PERFORM_TEST(test, argc, argv);
- return 0;
+ return 0;
}
//
// If you don't know or care about the units stuff, "px" and 96 should get you going.
-
/* Example Usage:
- // Load
- NSVGImage* image;
- image = nsvgParseFromFile("test.svg", "px", 96);
- printf("size: %f x %f\n", image->width, image->height);
- // Use...
- for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
- for (NSVGpath *path = shape->paths; path != NULL; path = path->next) {
- for (int i = 0; i < path->npts-1; i += 3) {
- float* p = &path->pts[i*2];
- drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
- }
- }
- }
- // Delete
- nsvgDelete(image);
+ // Load
+ NSVGImage* image;
+ image = nsvgParseFromFile("test.svg", "px", 96);
+ printf("size: %f x %f\n", image->width, image->height);
+ // Use...
+ for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
+ for (NSVGpath *path = shape->paths; path != NULL; path = path->next) {
+ for (int i = 0; i < path->npts-1; i += 3) {
+ float* p = &path->pts[i*2];
+ drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
+ }
+ }
+ }
+ // Delete
+ nsvgDelete(image);
*/
enum NSVGpaintType {
- NSVG_PAINT_NONE = 0,
- NSVG_PAINT_COLOR = 1,
- NSVG_PAINT_LINEAR_GRADIENT = 2,
- NSVG_PAINT_RADIAL_GRADIENT = 3
+ NSVG_PAINT_NONE = 0,
+ NSVG_PAINT_COLOR = 1,
+ NSVG_PAINT_LINEAR_GRADIENT = 2,
+ NSVG_PAINT_RADIAL_GRADIENT = 3
};
-enum NSVGspreadType {
- NSVG_SPREAD_PAD = 0,
- NSVG_SPREAD_REFLECT = 1,
- NSVG_SPREAD_REPEAT = 2
-};
+enum NSVGspreadType { NSVG_SPREAD_PAD = 0, NSVG_SPREAD_REFLECT = 1, NSVG_SPREAD_REPEAT = 2 };
-enum NSVGlineJoin {
- NSVG_JOIN_MITER = 0,
- NSVG_JOIN_ROUND = 1,
- NSVG_JOIN_BEVEL = 2
-};
+enum NSVGlineJoin { NSVG_JOIN_MITER = 0, NSVG_JOIN_ROUND = 1, NSVG_JOIN_BEVEL = 2 };
-enum NSVGlineCap {
- NSVG_CAP_BUTT = 0,
- NSVG_CAP_ROUND = 1,
- NSVG_CAP_SQUARE = 2
-};
+enum NSVGlineCap { NSVG_CAP_BUTT = 0, NSVG_CAP_ROUND = 1, NSVG_CAP_SQUARE = 2 };
-enum NSVGfillRule {
- NSVG_FILLRULE_NONZERO = 0,
- NSVG_FILLRULE_EVENODD = 1
-};
+enum NSVGfillRule { NSVG_FILLRULE_NONZERO = 0, NSVG_FILLRULE_EVENODD = 1 };
-enum NSVGflags {
- NSVG_FLAGS_VISIBLE = 0x01
-};
+enum NSVGflags { NSVG_FLAGS_VISIBLE = 0x01 };
typedef struct NSVGgradientStop {
- unsigned int color;
- float offset;
+ unsigned int color;
+ float offset;
} NSVGgradientStop;
typedef struct NSVGgradient {
- float xform[6];
- char spread;
- float fx, fy;
- int nstops;
- NSVGgradientStop stops[1];
+ float xform[6];
+ char spread;
+ float fx, fy;
+ int nstops;
+ NSVGgradientStop stops[1];
} NSVGgradient;
typedef struct NSVGpaint {
- char type;
- union {
- unsigned int color;
- NSVGgradient* gradient;
- };
+ char type;
+ union {
+ unsigned int color;
+ NSVGgradient *gradient;
+ };
} NSVGpaint;
-typedef struct NSVGpath
-{
- float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
- int npts; // Total number of bezier points.
- char closed; // Flag indicating if shapes should be treated as closed.
- float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
- struct NSVGpath* next; // Pointer to next path, or NULL if last element.
+typedef struct NSVGpath {
+ float *pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
+ int npts; // Total number of bezier points.
+ char closed; // Flag indicating if shapes should be treated as closed.
+ float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
+ struct NSVGpath *next; // Pointer to next path, or NULL if last element.
} NSVGpath;
-typedef struct NSVGshape
-{
- char id[64]; // Optional 'id' attr of the shape or its group
- NSVGpaint fill; // Fill paint
- NSVGpaint stroke; // Stroke paint
- float opacity; // Opacity of the shape.
- float strokeWidth; // Stroke width (scaled).
- float strokeDashOffset; // Stroke dash offset (scaled).
- float strokeDashArray[8]; // Stroke dash array (scaled).
- char strokeDashCount; // Number of dash values in dash array.
- char strokeLineJoin; // Stroke join type.
- char strokeLineCap; // Stroke cap type.
- float miterLimit; // Miter limit
- char fillRule; // Fill rule, see NSVGfillRule.
- unsigned char flags; // Logical or of NSVG_FLAGS_* flags
- float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
- NSVGpath* paths; // Linked list of paths in the image.
- struct NSVGshape* next; // Pointer to next shape, or NULL if last element.
+typedef struct NSVGshape {
+ char id[64]; // Optional 'id' attr of the shape or its group
+ NSVGpaint fill; // Fill paint
+ NSVGpaint stroke; // Stroke paint
+ float opacity; // Opacity of the shape.
+ float strokeWidth; // Stroke width (scaled).
+ float strokeDashOffset; // Stroke dash offset (scaled).
+ float strokeDashArray[8]; // Stroke dash array (scaled).
+ char strokeDashCount; // Number of dash values in dash array.
+ char strokeLineJoin; // Stroke join type.
+ char strokeLineCap; // Stroke cap type.
+ float miterLimit; // Miter limit
+ char fillRule; // Fill rule, see NSVGfillRule.
+ unsigned char flags; // Logical or of NSVG_FLAGS_* flags
+ float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
+ NSVGpath *paths; // Linked list of paths in the image.
+ struct NSVGshape *next; // Pointer to next shape, or NULL if last element.
} NSVGshape;
-typedef struct NSVGimage
-{
- float width; // Width of the image.
- float height; // Height of the image.
- NSVGshape* shapes; // Linked list of shapes in the image.
+typedef struct NSVGimage {
+ float width; // Width of the image.
+ float height; // Height of the image.
+ NSVGshape *shapes; // Linked list of shapes in the image.
} NSVGimage;
// Parses SVG file from a file, returns SVG image as paths.
-NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi);
+NSVGimage *nsvgParseFromFile(const char *filename, const char *units, float dpi);
// Parses SVG file from a null terminated string, returns SVG image as paths.
// Important note: changes the string.
-NSVGimage* nsvgParse(char* input, const char* units, float dpi);
+NSVGimage *nsvgParse(char *input, const char *units, float dpi);
// Deletes list of paths.
-void nsvgDelete(NSVGimage* image);
+void nsvgDelete(NSVGimage *image);
#ifdef __cplusplus
}
#include <stdlib.h>
#include <math.h>
-#define NSVG_PI (3.14159265358979323846264338327f)
-#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs.
+#define NSVG_PI (3.14159265358979323846264338327f)
+#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs.
-#define NSVG_ALIGN_MIN 0
-#define NSVG_ALIGN_MID 1
-#define NSVG_ALIGN_MAX 2
-#define NSVG_ALIGN_NONE 0
-#define NSVG_ALIGN_MEET 1
+#define NSVG_ALIGN_MIN 0
+#define NSVG_ALIGN_MID 1
+#define NSVG_ALIGN_MAX 2
+#define NSVG_ALIGN_NONE 0
+#define NSVG_ALIGN_MEET 1
#define NSVG_ALIGN_SLICE 2
-#define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0)
+#define NSVG_NOTUSED(v) \
+ do { \
+ (void)(1 ? (void)0 : ((void)(v))); \
+ } while (0)
#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))
#ifdef _MSC_VER
- #pragma warning (disable: 4996) // Switch off security warnings
- #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings
- #ifdef __cplusplus
- #define NSVG_INLINE inline
- #else
- #define NSVG_INLINE
- #endif
+#pragma warning(disable : 4996) // Switch off security warnings
+#pragma warning(disable : 4100) // Switch off unreferenced formal parameter warnings
+#ifdef __cplusplus
+#define NSVG_INLINE inline
#else
- #define NSVG_INLINE inline
+#define NSVG_INLINE
+#endif
+#else
+#define NSVG_INLINE inline
#endif
+static int nsvg__isspace(char c) { return strchr(" \t\n\v\f\r", c) != 0; }
-static int nsvg__isspace(char c)
-{
- return strchr(" \t\n\v\f\r", c) != 0;
-}
+static int nsvg__isdigit(char c) { return c >= '0' && c <= '9'; }
-static int nsvg__isdigit(char c)
-{
- return c >= '0' && c <= '9';
-}
-
-static int nsvg__isnum(char c)
-{
- return strchr("0123456789+-.eE", c) != 0;
-}
+static int nsvg__isnum(char c) { return strchr("0123456789+-.eE", c) != 0; }
static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; }
static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; }
-
// Simple XML parser
-#define NSVG_XML_TAG 1
-#define NSVG_XML_CONTENT 2
+#define NSVG_XML_TAG 1
+#define NSVG_XML_CONTENT 2
#define NSVG_XML_MAX_ATTRIBS 256
-static void nsvg__parseContent(char* s,
- void (*contentCb)(void* ud, const char* s),
- void* ud)
-{
- // Trim start white spaces
- while (*s && nsvg__isspace(*s)) s++;
- if (!*s) return;
-
- if (contentCb)
- (*contentCb)(ud, s);
-}
-
-static void nsvg__parseElement(char* s,
- void (*startelCb)(void* ud, const char* el, const char** attr),
- void (*endelCb)(void* ud, const char* el),
- void* ud)
-{
- const char* attr[NSVG_XML_MAX_ATTRIBS];
- int nattr = 0;
- char* name;
- int start = 0;
- int end = 0;
- char quote;
-
- // Skip white space after the '<'
- while (*s && nsvg__isspace(*s)) s++;
-
- // Check if the tag is end tag
- if (*s == '/') {
- s++;
- end = 1;
- } else {
- start = 1;
- }
-
- // Skip comments, data and preprocessor stuff.
- if (!*s || *s == '?' || *s == '!')
- return;
-
- // Get tag name
- name = s;
- while (*s && !nsvg__isspace(*s)) s++;
- if (*s) { *s++ = '\0'; }
-
- // Get attribs
- while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) {
- char* name = NULL;
- char* value = NULL;
-
- // Skip white space before the attrib name
- while (*s && nsvg__isspace(*s)) s++;
- if (!*s) break;
- if (*s == '/') {
- end = 1;
- break;
- }
- name = s;
- // Find end of the attrib name.
- while (*s && !nsvg__isspace(*s) && *s != '=') s++;
- if (*s) { *s++ = '\0'; }
- // Skip until the beginning of the value.
- while (*s && *s != '\"' && *s != '\'') s++;
- if (!*s) break;
- quote = *s;
- s++;
- // Store value and find the end of it.
- value = s;
- while (*s && *s != quote) s++;
- if (*s) { *s++ = '\0'; }
-
- // Store only well formed attributes
- if (name && value) {
- attr[nattr++] = name;
- attr[nattr++] = value;
- }
- }
-
- // List terminator
- attr[nattr++] = 0;
- attr[nattr++] = 0;
-
- // Call callbacks.
- if (start && startelCb)
- (*startelCb)(ud, name, attr);
- if (end && endelCb)
- (*endelCb)(ud, name);
-}
-
-int nsvg__parseXML(char* input,
- void (*startelCb)(void* ud, const char* el, const char** attr),
- void (*endelCb)(void* ud, const char* el),
- void (*contentCb)(void* ud, const char* s),
- void* ud)
-{
- char* s = input;
- char* mark = s;
- int state = NSVG_XML_CONTENT;
- while (*s) {
- if (*s == '<' && state == NSVG_XML_CONTENT) {
- // Start of a tag
- *s++ = '\0';
- nsvg__parseContent(mark, contentCb, ud);
- mark = s;
- state = NSVG_XML_TAG;
- } else if (*s == '>' && state == NSVG_XML_TAG) {
- // Start of a content or new tag.
- *s++ = '\0';
- nsvg__parseElement(mark, startelCb, endelCb, ud);
- mark = s;
- state = NSVG_XML_CONTENT;
- } else {
- s++;
- }
- }
-
- return 1;
+static void nsvg__parseContent(char *s, void (*contentCb)(void *ud, const char *s), void *ud) {
+ // Trim start white spaces
+ while (*s && nsvg__isspace(*s))
+ s++;
+ if (!*s)
+ return;
+
+ if (contentCb)
+ (*contentCb)(ud, s);
+}
+
+static void nsvg__parseElement(char *s, void (*startelCb)(void *ud, const char *el, const char **attr),
+ void (*endelCb)(void *ud, const char *el), void *ud) {
+ const char *attr[NSVG_XML_MAX_ATTRIBS];
+ int nattr = 0;
+ char *name;
+ int start = 0;
+ int end = 0;
+ char quote;
+
+ // Skip white space after the '<'
+ while (*s && nsvg__isspace(*s))
+ s++;
+
+ // Check if the tag is end tag
+ if (*s == '/') {
+ s++;
+ end = 1;
+ } else {
+ start = 1;
+ }
+
+ // Skip comments, data and preprocessor stuff.
+ if (!*s || *s == '?' || *s == '!')
+ return;
+
+ // Get tag name
+ name = s;
+ while (*s && !nsvg__isspace(*s))
+ s++;
+ if (*s) {
+ *s++ = '\0';
+ }
+
+ // Get attribs
+ while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS - 3) {
+ char *name = NULL;
+ char *value = NULL;
+
+ // Skip white space before the attrib name
+ while (*s && nsvg__isspace(*s))
+ s++;
+ if (!*s)
+ break;
+ if (*s == '/') {
+ end = 1;
+ break;
+ }
+ name = s;
+ // Find end of the attrib name.
+ while (*s && !nsvg__isspace(*s) && *s != '=')
+ s++;
+ if (*s) {
+ *s++ = '\0';
+ }
+ // Skip until the beginning of the value.
+ while (*s && *s != '\"' && *s != '\'')
+ s++;
+ if (!*s)
+ break;
+ quote = *s;
+ s++;
+ // Store value and find the end of it.
+ value = s;
+ while (*s && *s != quote)
+ s++;
+ if (*s) {
+ *s++ = '\0';
+ }
+
+ // Store only well formed attributes
+ if (name && value) {
+ attr[nattr++] = name;
+ attr[nattr++] = value;
+ }
+ }
+
+ // List terminator
+ attr[nattr++] = 0;
+ attr[nattr++] = 0;
+
+ // Call callbacks.
+ if (start && startelCb)
+ (*startelCb)(ud, name, attr);
+ if (end && endelCb)
+ (*endelCb)(ud, name);
+}
+
+int nsvg__parseXML(char *input, void (*startelCb)(void *ud, const char *el, const char **attr),
+ void (*endelCb)(void *ud, const char *el), void (*contentCb)(void *ud, const char *s), void *ud) {
+ char *s = input;
+ char *mark = s;
+ int state = NSVG_XML_CONTENT;
+ while (*s) {
+ if (*s == '<' && state == NSVG_XML_CONTENT) {
+ // Start of a tag
+ *s++ = '\0';
+ nsvg__parseContent(mark, contentCb, ud);
+ mark = s;
+ state = NSVG_XML_TAG;
+ } else if (*s == '>' && state == NSVG_XML_TAG) {
+ // Start of a content or new tag.
+ *s++ = '\0';
+ nsvg__parseElement(mark, startelCb, endelCb, ud);
+ mark = s;
+ state = NSVG_XML_CONTENT;
+ } else {
+ s++;
+ }
+ }
+
+ return 1;
}
-
/* Simple SVG parser. */
#define NSVG_MAX_ATTR 128
-enum NSVGgradientUnits {
- NSVG_USER_SPACE = 0,
- NSVG_OBJECT_SPACE = 1
-};
+enum NSVGgradientUnits { NSVG_USER_SPACE = 0, NSVG_OBJECT_SPACE = 1 };
#define NSVG_MAX_DASHES 8
enum NSVGunits {
- NSVG_UNITS_USER,
- NSVG_UNITS_PX,
- NSVG_UNITS_PT,
- NSVG_UNITS_PC,
- NSVG_UNITS_MM,
- NSVG_UNITS_CM,
- NSVG_UNITS_IN,
- NSVG_UNITS_PERCENT,
- NSVG_UNITS_EM,
- NSVG_UNITS_EX
+ NSVG_UNITS_USER,
+ NSVG_UNITS_PX,
+ NSVG_UNITS_PT,
+ NSVG_UNITS_PC,
+ NSVG_UNITS_MM,
+ NSVG_UNITS_CM,
+ NSVG_UNITS_IN,
+ NSVG_UNITS_PERCENT,
+ NSVG_UNITS_EM,
+ NSVG_UNITS_EX
};
typedef struct NSVGcoordinate {
- float value;
- int units;
+ float value;
+ int units;
} NSVGcoordinate;
typedef struct NSVGlinearData {
- NSVGcoordinate x1, y1, x2, y2;
+ NSVGcoordinate x1, y1, x2, y2;
} NSVGlinearData;
typedef struct NSVGradialData {
- NSVGcoordinate cx, cy, r, fx, fy;
+ NSVGcoordinate cx, cy, r, fx, fy;
} NSVGradialData;
-typedef struct NSVGgradientData
-{
- char id[64];
- char ref[64];
- char type;
- union {
- NSVGlinearData linear;
- NSVGradialData radial;
- };
- char spread;
- char units;
- float xform[6];
- int nstops;
- NSVGgradientStop* stops;
- struct NSVGgradientData* next;
+typedef struct NSVGgradientData {
+ char id[64];
+ char ref[64];
+ char type;
+ union {
+ NSVGlinearData linear;
+ NSVGradialData radial;
+ };
+ char spread;
+ char units;
+ float xform[6];
+ int nstops;
+ NSVGgradientStop *stops;
+ struct NSVGgradientData *next;
} NSVGgradientData;
-typedef struct NSVGattrib
-{
- char id[64];
- float xform[6];
- unsigned int fillColor;
- unsigned int strokeColor;
- float opacity;
- float fillOpacity;
- float strokeOpacity;
- char fillGradient[64];
- char strokeGradient[64];
- float strokeWidth;
- float strokeDashOffset;
- float strokeDashArray[NSVG_MAX_DASHES];
- int strokeDashCount;
- char strokeLineJoin;
- char strokeLineCap;
- float miterLimit;
- char fillRule;
- float fontSize;
- unsigned int stopColor;
- float stopOpacity;
- float stopOffset;
- char hasFill;
- char hasStroke;
- char visible;
+typedef struct NSVGattrib {
+ char id[64];
+ float xform[6];
+ unsigned int fillColor;
+ unsigned int strokeColor;
+ float opacity;
+ float fillOpacity;
+ float strokeOpacity;
+ char fillGradient[64];
+ char strokeGradient[64];
+ float strokeWidth;
+ float strokeDashOffset;
+ float strokeDashArray[NSVG_MAX_DASHES];
+ int strokeDashCount;
+ char strokeLineJoin;
+ char strokeLineCap;
+ float miterLimit;
+ char fillRule;
+ float fontSize;
+ unsigned int stopColor;
+ float stopOpacity;
+ float stopOffset;
+ char hasFill;
+ char hasStroke;
+ char visible;
} NSVGattrib;
-typedef struct NSVGparser
-{
- NSVGattrib attr[NSVG_MAX_ATTR];
- int attrHead;
- float* pts;
- int npts;
- int cpts;
- NSVGpath* plist;
- NSVGimage* image;
- NSVGgradientData* gradients;
- NSVGshape* shapesTail;
- float viewMinx, viewMiny, viewWidth, viewHeight;
- int alignX, alignY, alignType;
- float dpi;
- char pathFlag;
- char defsFlag;
+typedef struct NSVGparser {
+ NSVGattrib attr[NSVG_MAX_ATTR];
+ int attrHead;
+ float *pts;
+ int npts;
+ int cpts;
+ NSVGpath *plist;
+ NSVGimage *image;
+ NSVGgradientData *gradients;
+ NSVGshape *shapesTail;
+ float viewMinx, viewMiny, viewWidth, viewHeight;
+ int alignX, alignY, alignType;
+ float dpi;
+ char pathFlag;
+ char defsFlag;
} NSVGparser;
-static void nsvg__xformIdentity(float* t)
-{
- t[0] = 1.0f; t[1] = 0.0f;
- t[2] = 0.0f; t[3] = 1.0f;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetTranslation(float* t, float tx, float ty)
-{
- t[0] = 1.0f; t[1] = 0.0f;
- t[2] = 0.0f; t[3] = 1.0f;
- t[4] = tx; t[5] = ty;
-}
-
-static void nsvg__xformSetScale(float* t, float sx, float sy)
-{
- t[0] = sx; t[1] = 0.0f;
- t[2] = 0.0f; t[3] = sy;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetSkewX(float* t, float a)
-{
- t[0] = 1.0f; t[1] = 0.0f;
- t[2] = tanf(a); t[3] = 1.0f;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetSkewY(float* t, float a)
-{
- t[0] = 1.0f; t[1] = tanf(a);
- t[2] = 0.0f; t[3] = 1.0f;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetRotation(float* t, float a)
-{
- float cs = cosf(a), sn = sinf(a);
- t[0] = cs; t[1] = sn;
- t[2] = -sn; t[3] = cs;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformMultiply(float* t, float* s)
-{
- float t0 = t[0] * s[0] + t[1] * s[2];
- float t2 = t[2] * s[0] + t[3] * s[2];
- float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
- t[1] = t[0] * s[1] + t[1] * s[3];
- t[3] = t[2] * s[1] + t[3] * s[3];
- t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
- t[0] = t0;
- t[2] = t2;
- t[4] = t4;
-}
-
-static void nsvg__xformInverse(float* inv, float* t)
-{
- double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
- if (det > -1e-6 && det < 1e-6) {
- nsvg__xformIdentity(t);
- return;
- }
- invdet = 1.0 / det;
- inv[0] = (float)(t[3] * invdet);
- inv[2] = (float)(-t[2] * invdet);
- inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
- inv[1] = (float)(-t[1] * invdet);
- inv[3] = (float)(t[0] * invdet);
- inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
-}
-
-static void nsvg__xformPremultiply(float* t, float* s)
-{
- float s2[6];
- memcpy(s2, s, sizeof(float)*6);
- nsvg__xformMultiply(s2, t);
- memcpy(t, s2, sizeof(float)*6);
-}
-
-static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t)
-{
- *dx = x*t[0] + y*t[2] + t[4];
- *dy = x*t[1] + y*t[3] + t[5];
-}
-
-static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t)
-{
- *dx = x*t[0] + y*t[2];
- *dy = x*t[1] + y*t[3];
+static void nsvg__xformIdentity(float *t) {
+ t[0] = 1.0f;
+ t[1] = 0.0f;
+ t[2] = 0.0f;
+ t[3] = 1.0f;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetTranslation(float *t, float tx, float ty) {
+ t[0] = 1.0f;
+ t[1] = 0.0f;
+ t[2] = 0.0f;
+ t[3] = 1.0f;
+ t[4] = tx;
+ t[5] = ty;
+}
+
+static void nsvg__xformSetScale(float *t, float sx, float sy) {
+ t[0] = sx;
+ t[1] = 0.0f;
+ t[2] = 0.0f;
+ t[3] = sy;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetSkewX(float *t, float a) {
+ t[0] = 1.0f;
+ t[1] = 0.0f;
+ t[2] = tanf(a);
+ t[3] = 1.0f;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetSkewY(float *t, float a) {
+ t[0] = 1.0f;
+ t[1] = tanf(a);
+ t[2] = 0.0f;
+ t[3] = 1.0f;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetRotation(float *t, float a) {
+ float cs = cosf(a), sn = sinf(a);
+ t[0] = cs;
+ t[1] = sn;
+ t[2] = -sn;
+ t[3] = cs;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformMultiply(float *t, float *s) {
+ float t0 = t[0] * s[0] + t[1] * s[2];
+ float t2 = t[2] * s[0] + t[3] * s[2];
+ float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
+ t[1] = t[0] * s[1] + t[1] * s[3];
+ t[3] = t[2] * s[1] + t[3] * s[3];
+ t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
+ t[0] = t0;
+ t[2] = t2;
+ t[4] = t4;
+}
+
+static void nsvg__xformInverse(float *inv, float *t) {
+ double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
+ if (det > -1e-6 && det < 1e-6) {
+ nsvg__xformIdentity(t);
+ return;
+ }
+ invdet = 1.0 / det;
+ inv[0] = (float)(t[3] * invdet);
+ inv[2] = (float)(-t[2] * invdet);
+ inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
+ inv[1] = (float)(-t[1] * invdet);
+ inv[3] = (float)(t[0] * invdet);
+ inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
+}
+
+static void nsvg__xformPremultiply(float *t, float *s) {
+ float s2[6];
+ memcpy(s2, s, sizeof(float) * 6);
+ nsvg__xformMultiply(s2, t);
+ memcpy(t, s2, sizeof(float) * 6);
+}
+
+static void nsvg__xformPoint(float *dx, float *dy, float x, float y, float *t) {
+ *dx = x * t[0] + y * t[2] + t[4];
+ *dy = x * t[1] + y * t[3] + t[5];
+}
+
+static void nsvg__xformVec(float *dx, float *dy, float x, float y, float *t) {
+ *dx = x * t[0] + y * t[2];
+ *dy = x * t[1] + y * t[3];
}
#define NSVG_EPSILON (1e-12)
-static int nsvg__ptInBounds(float* pt, float* bounds)
-{
- return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];
-}
-
-
-static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3)
-{
- double it = 1.0-t;
- return it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3;
-}
-
-static void nsvg__curveBounds(float* bounds, float* curve)
-{
- int i, j, count;
- double roots[2], a, b, c, b2ac, t, v;
- float* v0 = &curve[0];
- float* v1 = &curve[2];
- float* v2 = &curve[4];
- float* v3 = &curve[6];
-
- // Start the bounding box by end points
- bounds[0] = nsvg__minf(v0[0], v3[0]);
- bounds[1] = nsvg__minf(v0[1], v3[1]);
- bounds[2] = nsvg__maxf(v0[0], v3[0]);
- bounds[3] = nsvg__maxf(v0[1], v3[1]);
-
- // Bezier curve fits inside the convex hull of it's control points.
- // If control points are inside the bounds, we're done.
- if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))
- return;
-
- // Add bezier curve inflection points in X and Y.
- for (i = 0; i < 2; i++) {
- a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i];
- b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i];
- c = 3.0 * v1[i] - 3.0 * v0[i];
- count = 0;
- if (fabs(a) < NSVG_EPSILON) {
- if (fabs(b) > NSVG_EPSILON) {
- t = -c / b;
- if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
- roots[count++] = t;
- }
- } else {
- b2ac = b*b - 4.0*c*a;
- if (b2ac > NSVG_EPSILON) {
- t = (-b + sqrt(b2ac)) / (2.0 * a);
- if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
- roots[count++] = t;
- t = (-b - sqrt(b2ac)) / (2.0 * a);
- if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
- roots[count++] = t;
- }
- }
- for (j = 0; j < count; j++) {
- v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);
- bounds[0+i] = nsvg__minf(bounds[0+i], (float)v);
- bounds[2+i] = nsvg__maxf(bounds[2+i], (float)v);
- }
- }
-}
-
-static NSVGparser* nsvg__createParser()
-{
- NSVGparser* p;
- p = (NSVGparser*)malloc(sizeof(NSVGparser));
- if (p == NULL) goto error;
- memset(p, 0, sizeof(NSVGparser));
-
- p->image = (NSVGimage*)malloc(sizeof(NSVGimage));
- if (p->image == NULL) goto error;
- memset(p->image, 0, sizeof(NSVGimage));
-
- // Init style
- nsvg__xformIdentity(p->attr[0].xform);
- memset(p->attr[0].id, 0, sizeof p->attr[0].id);
- p->attr[0].fillColor = NSVG_RGB(0,0,0);
- p->attr[0].strokeColor = NSVG_RGB(0,0,0);
- p->attr[0].opacity = 1;
- p->attr[0].fillOpacity = 1;
- p->attr[0].strokeOpacity = 1;
- p->attr[0].stopOpacity = 1;
- p->attr[0].strokeWidth = 1;
- p->attr[0].strokeLineJoin = NSVG_JOIN_MITER;
- p->attr[0].strokeLineCap = NSVG_CAP_BUTT;
- p->attr[0].miterLimit = 4;
- p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
- p->attr[0].hasFill = 1;
- p->attr[0].visible = 1;
-
- return p;
+static int nsvg__ptInBounds(float *pt, float *bounds) {
+ return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];
+}
+
+static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3) {
+ double it = 1.0 - t;
+ return it * it * it * p0 + 3.0 * it * it * t * p1 + 3.0 * it * t * t * p2 + t * t * t * p3;
+}
+
+static void nsvg__curveBounds(float *bounds, float *curve) {
+ int i, j, count;
+ double roots[2], a, b, c, b2ac, t, v;
+ float *v0 = &curve[0];
+ float *v1 = &curve[2];
+ float *v2 = &curve[4];
+ float *v3 = &curve[6];
+
+ // Start the bounding box by end points
+ bounds[0] = nsvg__minf(v0[0], v3[0]);
+ bounds[1] = nsvg__minf(v0[1], v3[1]);
+ bounds[2] = nsvg__maxf(v0[0], v3[0]);
+ bounds[3] = nsvg__maxf(v0[1], v3[1]);
+
+ // Bezier curve fits inside the convex hull of it's control points.
+ // If control points are inside the bounds, we're done.
+ if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))
+ return;
+
+ // Add bezier curve inflection points in X and Y.
+ for (i = 0; i < 2; i++) {
+ a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i];
+ b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i];
+ c = 3.0 * v1[i] - 3.0 * v0[i];
+ count = 0;
+ if (fabs(a) < NSVG_EPSILON) {
+ if (fabs(b) > NSVG_EPSILON) {
+ t = -c / b;
+ if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON)
+ roots[count++] = t;
+ }
+ } else {
+ b2ac = b * b - 4.0 * c * a;
+ if (b2ac > NSVG_EPSILON) {
+ t = (-b + sqrt(b2ac)) / (2.0 * a);
+ if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON)
+ roots[count++] = t;
+ t = (-b - sqrt(b2ac)) / (2.0 * a);
+ if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON)
+ roots[count++] = t;
+ }
+ }
+ for (j = 0; j < count; j++) {
+ v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);
+ bounds[0 + i] = nsvg__minf(bounds[0 + i], (float)v);
+ bounds[2 + i] = nsvg__maxf(bounds[2 + i], (float)v);
+ }
+ }
+}
+
+static NSVGparser *nsvg__createParser() {
+ NSVGparser *p;
+ p = (NSVGparser *)malloc(sizeof(NSVGparser));
+ if (p == NULL)
+ goto error;
+ memset(p, 0, sizeof(NSVGparser));
+
+ p->image = (NSVGimage *)malloc(sizeof(NSVGimage));
+ if (p->image == NULL)
+ goto error;
+ memset(p->image, 0, sizeof(NSVGimage));
+
+ // Init style
+ nsvg__xformIdentity(p->attr[0].xform);
+ memset(p->attr[0].id, 0, sizeof p->attr[0].id);
+ p->attr[0].fillColor = NSVG_RGB(0, 0, 0);
+ p->attr[0].strokeColor = NSVG_RGB(0, 0, 0);
+ p->attr[0].opacity = 1;
+ p->attr[0].fillOpacity = 1;
+ p->attr[0].strokeOpacity = 1;
+ p->attr[0].stopOpacity = 1;
+ p->attr[0].strokeWidth = 1;
+ p->attr[0].strokeLineJoin = NSVG_JOIN_MITER;
+ p->attr[0].strokeLineCap = NSVG_CAP_BUTT;
+ p->attr[0].miterLimit = 4;
+ p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
+ p->attr[0].hasFill = 1;
+ p->attr[0].visible = 1;
+
+ return p;
error:
- if (p) {
- if (p->image) free(p->image);
- free(p);
- }
- return NULL;
-}
-
-static void nsvg__deletePaths(NSVGpath* path)
-{
- while (path) {
- NSVGpath *next = path->next;
- if (path->pts != NULL)
- free(path->pts);
- free(path);
- path = next;
- }
-}
-
-static void nsvg__deletePaint(NSVGpaint* paint)
-{
- if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT)
- free(paint->gradient);
+ if (p) {
+ if (p->image)
+ free(p->image);
+ free(p);
+ }
+ return NULL;
}
-
-static void nsvg__deleteGradientData(NSVGgradientData* grad)
-{
- NSVGgradientData* next;
- while (grad != NULL) {
- next = grad->next;
- free(grad->stops);
- free(grad);
- grad = next;
- }
+
+static void nsvg__deletePaths(NSVGpath *path) {
+ while (path) {
+ NSVGpath *next = path->next;
+ if (path->pts != NULL)
+ free(path->pts);
+ free(path);
+ path = next;
+ }
}
-static void nsvg__deleteParser(NSVGparser* p)
-{
- if (p != NULL) {
- nsvg__deletePaths(p->plist);
- nsvg__deleteGradientData(p->gradients);
- nsvgDelete(p->image);
- free(p->pts);
- free(p);
- }
+static void nsvg__deletePaint(NSVGpaint *paint) {
+ if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT)
+ free(paint->gradient);
}
-static void nsvg__resetPath(NSVGparser* p)
-{
- p->npts = 0;
-}
-
-static void nsvg__addPoint(NSVGparser* p, float x, float y)
-{
- if (p->npts+1 > p->cpts) {
- p->cpts = p->cpts ? p->cpts*2 : 8;
- p->pts = (float*)realloc(p->pts, p->cpts*2*sizeof(float));
- if (!p->pts) return;
- }
- p->pts[p->npts*2+0] = x;
- p->pts[p->npts*2+1] = y;
- p->npts++;
-}
-
-static void nsvg__moveTo(NSVGparser* p, float x, float y)
-{
- if (p->npts > 0) {
- p->pts[(p->npts-1)*2+0] = x;
- p->pts[(p->npts-1)*2+1] = y;
- } else {
- nsvg__addPoint(p, x, y);
- }
-}
-
-static void nsvg__lineTo(NSVGparser* p, float x, float y)
-{
- float px,py, dx,dy;
- if (p->npts > 0) {
- px = p->pts[(p->npts-1)*2+0];
- py = p->pts[(p->npts-1)*2+1];
- dx = x - px;
- dy = y - py;
- nsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f);
- nsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f);
- nsvg__addPoint(p, x, y);
- }
-}
-
-static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)
-{
- nsvg__addPoint(p, cpx1, cpy1);
- nsvg__addPoint(p, cpx2, cpy2);
- nsvg__addPoint(p, x, y);
-}
-
-static NSVGattrib* nsvg__getAttr(NSVGparser* p)
-{
- return &p->attr[p->attrHead];
-}
-
-static void nsvg__pushAttr(NSVGparser* p)
-{
- if (p->attrHead < NSVG_MAX_ATTR-1) {
- p->attrHead++;
- memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead-1], sizeof(NSVGattrib));
- }
-}
-
-static void nsvg__popAttr(NSVGparser* p)
-{
- if (p->attrHead > 0)
- p->attrHead--;
-}
-
-static float nsvg__actualOrigX(NSVGparser* p)
-{
- return p->viewMinx;
-}
-
-static float nsvg__actualOrigY(NSVGparser* p)
-{
- return p->viewMiny;
-}
-
-static float nsvg__actualWidth(NSVGparser* p)
-{
- return p->viewWidth;
-}
-
-static float nsvg__actualHeight(NSVGparser* p)
-{
- return p->viewHeight;
-}
-
-static float nsvg__actualLength(NSVGparser* p)
-{
- float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p);
- return sqrtf(w*w + h*h) / sqrtf(2.0f);
-}
-
-static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- switch (c.units) {
- case NSVG_UNITS_USER: return c.value;
- case NSVG_UNITS_PX: return c.value;
- case NSVG_UNITS_PT: return c.value / 72.0f * p->dpi;
- case NSVG_UNITS_PC: return c.value / 6.0f * p->dpi;
- case NSVG_UNITS_MM: return c.value / 25.4f * p->dpi;
- case NSVG_UNITS_CM: return c.value / 2.54f * p->dpi;
- case NSVG_UNITS_IN: return c.value * p->dpi;
- case NSVG_UNITS_EM: return c.value * attr->fontSize;
- case NSVG_UNITS_EX: return c.value * attr->fontSize * 0.52f; // x-height of Helvetica.
- case NSVG_UNITS_PERCENT: return orig + c.value / 100.0f * length;
- default: return c.value;
- }
- return c.value;
-}
-
-static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id)
-{
- NSVGgradientData* grad = p->gradients;
- while (grad) {
- if (strcmp(grad->id, id) == 0)
- return grad;
- grad = grad->next;
- }
- return NULL;
-}
-
-static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, char* paintType)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- NSVGgradientData* data = NULL;
- NSVGgradientData* ref = NULL;
- NSVGgradientStop* stops = NULL;
- NSVGgradient* grad;
- float ox, oy, sw, sh, sl;
- int nstops = 0;
-
- data = nsvg__findGradientData(p, id);
- if (data == NULL) return NULL;
-
- // TODO: use ref to fill in all unset values too.
- ref = data;
- while (ref != NULL) {
- if (stops == NULL && ref->stops != NULL) {
- stops = ref->stops;
- nstops = ref->nstops;
- break;
- }
- ref = nsvg__findGradientData(p, ref->ref);
- }
- if (stops == NULL) return NULL;
-
- grad = (NSVGgradient*)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop)*(nstops-1));
- if (grad == NULL) return NULL;
-
- // The shape width and height.
- if (data->units == NSVG_OBJECT_SPACE) {
- ox = localBounds[0];
- oy = localBounds[1];
- sw = localBounds[2] - localBounds[0];
- sh = localBounds[3] - localBounds[1];
- } else {
- ox = nsvg__actualOrigX(p);
- oy = nsvg__actualOrigY(p);
- sw = nsvg__actualWidth(p);
- sh = nsvg__actualHeight(p);
- }
- sl = sqrtf(sw*sw + sh*sh) / sqrtf(2.0f);
-
- if (data->type == NSVG_PAINT_LINEAR_GRADIENT) {
- float x1, y1, x2, y2, dx, dy;
- x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw);
- y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh);
- x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw);
- y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh);
- // Calculate transform aligned to the line
- dx = x2 - x1;
- dy = y2 - y1;
- grad->xform[0] = dy; grad->xform[1] = -dx;
- grad->xform[2] = dx; grad->xform[3] = dy;
- grad->xform[4] = x1; grad->xform[5] = y1;
- } else {
- float cx, cy, fx, fy, r;
- cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw);
- cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh);
- fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw);
- fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh);
- r = nsvg__convertToPixels(p, data->radial.r, 0, sl);
- // Calculate transform aligned to the circle
- grad->xform[0] = r; grad->xform[1] = 0;
- grad->xform[2] = 0; grad->xform[3] = r;
- grad->xform[4] = cx; grad->xform[5] = cy;
- grad->fx = fx / r;
- grad->fy = fy / r;
- }
-
- nsvg__xformMultiply(grad->xform, data->xform);
- nsvg__xformMultiply(grad->xform, attr->xform);
-
- grad->spread = data->spread;
- memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));
- grad->nstops = nstops;
-
- *paintType = data->type;
-
- return grad;
-}
-
-static float nsvg__getAverageScale(float* t)
-{
- float sx = sqrtf(t[0]*t[0] + t[2]*t[2]);
- float sy = sqrtf(t[1]*t[1] + t[3]*t[3]);
- return (sx + sy) * 0.5f;
-}
-
-static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform)
-{
- NSVGpath* path;
- float curve[4*2], curveBounds[4];
- int i, first = 1;
- for (path = shape->paths; path != NULL; path = path->next) {
- nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform);
- for (i = 0; i < path->npts-1; i += 3) {
- nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i+1)*2], path->pts[(i+1)*2+1], xform);
- nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i+2)*2], path->pts[(i+2)*2+1], xform);
- nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i+3)*2], path->pts[(i+3)*2+1], xform);
- nsvg__curveBounds(curveBounds, curve);
- if (first) {
- bounds[0] = curveBounds[0];
- bounds[1] = curveBounds[1];
- bounds[2] = curveBounds[2];
- bounds[3] = curveBounds[3];
- first = 0;
- } else {
- bounds[0] = nsvg__minf(bounds[0], curveBounds[0]);
- bounds[1] = nsvg__minf(bounds[1], curveBounds[1]);
- bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);
- bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);
- }
- curve[0] = curve[6];
- curve[1] = curve[7];
- }
- }
-}
-
-static void nsvg__addShape(NSVGparser* p)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- float scale = 1.0f;
- NSVGshape* shape;
- NSVGpath* path;
- int i;
-
- if (p->plist == NULL)
- return;
-
- shape = (NSVGshape*)malloc(sizeof(NSVGshape));
- if (shape == NULL) goto error;
- memset(shape, 0, sizeof(NSVGshape));
-
- memcpy(shape->id, attr->id, sizeof shape->id);
- scale = nsvg__getAverageScale(attr->xform);
- shape->strokeWidth = attr->strokeWidth * scale;
- shape->strokeDashOffset = attr->strokeDashOffset * scale;
- shape->strokeDashCount = (char)attr->strokeDashCount;
- for (i = 0; i < attr->strokeDashCount; i++)
- shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
- shape->strokeLineJoin = attr->strokeLineJoin;
- shape->strokeLineCap = attr->strokeLineCap;
- shape->miterLimit = attr->miterLimit;
- shape->fillRule = attr->fillRule;
- shape->opacity = attr->opacity;
-
- shape->paths = p->plist;
- p->plist = NULL;
-
- // Calculate shape bounds
- shape->bounds[0] = shape->paths->bounds[0];
- shape->bounds[1] = shape->paths->bounds[1];
- shape->bounds[2] = shape->paths->bounds[2];
- shape->bounds[3] = shape->paths->bounds[3];
- for (path = shape->paths->next; path != NULL; path = path->next) {
- shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
- shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);
- shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);
- shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);
- }
-
- // Set fill
- if (attr->hasFill == 0) {
- shape->fill.type = NSVG_PAINT_NONE;
- } else if (attr->hasFill == 1) {
- shape->fill.type = NSVG_PAINT_COLOR;
- shape->fill.color = attr->fillColor;
- shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24;
- } else if (attr->hasFill == 2) {
- float inv[6], localBounds[4];
- nsvg__xformInverse(inv, attr->xform);
- nsvg__getLocalBounds(localBounds, shape, inv);
- shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type);
- if (shape->fill.gradient == NULL) {
- shape->fill.type = NSVG_PAINT_NONE;
- }
- }
-
- // Set stroke
- if (attr->hasStroke == 0) {
- shape->stroke.type = NSVG_PAINT_NONE;
- } else if (attr->hasStroke == 1) {
- shape->stroke.type = NSVG_PAINT_COLOR;
- shape->stroke.color = attr->strokeColor;
- shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24;
- } else if (attr->hasStroke == 2) {
- float inv[6], localBounds[4];
- nsvg__xformInverse(inv, attr->xform);
- nsvg__getLocalBounds(localBounds, shape, inv);
- shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type);
- if (shape->stroke.gradient == NULL)
- shape->stroke.type = NSVG_PAINT_NONE;
- }
-
- // Set flags
- shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00);
-
- // Add to tail
- if (p->image->shapes == NULL)
- p->image->shapes = shape;
- else
- p->shapesTail->next = shape;
- p->shapesTail = shape;
-
- return;
+static void nsvg__deleteGradientData(NSVGgradientData *grad) {
+ NSVGgradientData *next;
+ while (grad != NULL) {
+ next = grad->next;
+ free(grad->stops);
+ free(grad);
+ grad = next;
+ }
+}
+
+static void nsvg__deleteParser(NSVGparser *p) {
+ if (p != NULL) {
+ nsvg__deletePaths(p->plist);
+ nsvg__deleteGradientData(p->gradients);
+ nsvgDelete(p->image);
+ free(p->pts);
+ free(p);
+ }
+}
+
+static void nsvg__resetPath(NSVGparser *p) { p->npts = 0; }
+
+static void nsvg__addPoint(NSVGparser *p, float x, float y) {
+ if (p->npts + 1 > p->cpts) {
+ p->cpts = p->cpts ? p->cpts * 2 : 8;
+ p->pts = (float *)realloc(p->pts, p->cpts * 2 * sizeof(float));
+ if (!p->pts)
+ return;
+ }
+ p->pts[p->npts * 2 + 0] = x;
+ p->pts[p->npts * 2 + 1] = y;
+ p->npts++;
+}
+
+static void nsvg__moveTo(NSVGparser *p, float x, float y) {
+ if (p->npts > 0) {
+ p->pts[(p->npts - 1) * 2 + 0] = x;
+ p->pts[(p->npts - 1) * 2 + 1] = y;
+ } else {
+ nsvg__addPoint(p, x, y);
+ }
+}
+
+static void nsvg__lineTo(NSVGparser *p, float x, float y) {
+ float px, py, dx, dy;
+ if (p->npts > 0) {
+ px = p->pts[(p->npts - 1) * 2 + 0];
+ py = p->pts[(p->npts - 1) * 2 + 1];
+ dx = x - px;
+ dy = y - py;
+ nsvg__addPoint(p, px + dx / 3.0f, py + dy / 3.0f);
+ nsvg__addPoint(p, x - dx / 3.0f, y - dy / 3.0f);
+ nsvg__addPoint(p, x, y);
+ }
+}
+
+static void nsvg__cubicBezTo(NSVGparser *p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y) {
+ nsvg__addPoint(p, cpx1, cpy1);
+ nsvg__addPoint(p, cpx2, cpy2);
+ nsvg__addPoint(p, x, y);
+}
+
+static NSVGattrib *nsvg__getAttr(NSVGparser *p) { return &p->attr[p->attrHead]; }
+
+static void nsvg__pushAttr(NSVGparser *p) {
+ if (p->attrHead < NSVG_MAX_ATTR - 1) {
+ p->attrHead++;
+ memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead - 1], sizeof(NSVGattrib));
+ }
+}
+
+static void nsvg__popAttr(NSVGparser *p) {
+ if (p->attrHead > 0)
+ p->attrHead--;
+}
+
+static float nsvg__actualOrigX(NSVGparser *p) { return p->viewMinx; }
+
+static float nsvg__actualOrigY(NSVGparser *p) { return p->viewMiny; }
+
+static float nsvg__actualWidth(NSVGparser *p) { return p->viewWidth; }
+
+static float nsvg__actualHeight(NSVGparser *p) { return p->viewHeight; }
+
+static float nsvg__actualLength(NSVGparser *p) {
+ float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p);
+ return sqrtf(w * w + h * h) / sqrtf(2.0f);
+}
+
+static float nsvg__convertToPixels(NSVGparser *p, NSVGcoordinate c, float orig, float length) {
+ NSVGattrib *attr = nsvg__getAttr(p);
+ switch (c.units) {
+ case NSVG_UNITS_USER:
+ return c.value;
+ case NSVG_UNITS_PX:
+ return c.value;
+ case NSVG_UNITS_PT:
+ return c.value / 72.0f * p->dpi;
+ case NSVG_UNITS_PC:
+ return c.value / 6.0f * p->dpi;
+ case NSVG_UNITS_MM:
+ return c.value / 25.4f * p->dpi;
+ case NSVG_UNITS_CM:
+ return c.value / 2.54f * p->dpi;
+ case NSVG_UNITS_IN:
+ return c.value * p->dpi;
+ case NSVG_UNITS_EM:
+ return c.value * attr->fontSize;
+ case NSVG_UNITS_EX:
+ return c.value * attr->fontSize * 0.52f; // x-height of Helvetica.
+ case NSVG_UNITS_PERCENT:
+ return orig + c.value / 100.0f * length;
+ default:
+ return c.value;
+ }
+ return c.value;
+}
+
+static NSVGgradientData *nsvg__findGradientData(NSVGparser *p, const char *id) {
+ NSVGgradientData *grad = p->gradients;
+ while (grad) {
+ if (strcmp(grad->id, id) == 0)
+ return grad;
+ grad = grad->next;
+ }
+ return NULL;
+}
+
+static NSVGgradient *nsvg__createGradient(NSVGparser *p, const char *id, const float *localBounds, char *paintType) {
+ NSVGattrib *attr = nsvg__getAttr(p);
+ NSVGgradientData *data = NULL;
+ NSVGgradientData *ref = NULL;
+ NSVGgradientStop *stops = NULL;
+ NSVGgradient *grad;
+ float ox, oy, sw, sh, sl;
+ int nstops = 0;
+
+ data = nsvg__findGradientData(p, id);
+ if (data == NULL)
+ return NULL;
+
+ // TODO: use ref to fill in all unset values too.
+ ref = data;
+ while (ref != NULL) {
+ if (stops == NULL && ref->stops != NULL) {
+ stops = ref->stops;
+ nstops = ref->nstops;
+ break;
+ }
+ ref = nsvg__findGradientData(p, ref->ref);
+ }
+ if (stops == NULL)
+ return NULL;
+
+ grad = (NSVGgradient *)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop) * (nstops - 1));
+ if (grad == NULL)
+ return NULL;
+
+ // The shape width and height.
+ if (data->units == NSVG_OBJECT_SPACE) {
+ ox = localBounds[0];
+ oy = localBounds[1];
+ sw = localBounds[2] - localBounds[0];
+ sh = localBounds[3] - localBounds[1];
+ } else {
+ ox = nsvg__actualOrigX(p);
+ oy = nsvg__actualOrigY(p);
+ sw = nsvg__actualWidth(p);
+ sh = nsvg__actualHeight(p);
+ }
+ sl = sqrtf(sw * sw + sh * sh) / sqrtf(2.0f);
+
+ if (data->type == NSVG_PAINT_LINEAR_GRADIENT) {
+ float x1, y1, x2, y2, dx, dy;
+ x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw);
+ y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh);
+ x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw);
+ y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh);
+ // Calculate transform aligned to the line
+ dx = x2 - x1;
+ dy = y2 - y1;
+ grad->xform[0] = dy;
+ grad->xform[1] = -dx;
+ grad->xform[2] = dx;
+ grad->xform[3] = dy;
+ grad->xform[4] = x1;
+ grad->xform[5] = y1;
+ } else {
+ float cx, cy, fx, fy, r;
+ cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw);
+ cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh);
+ fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw);
+ fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh);
+ r = nsvg__convertToPixels(p, data->radial.r, 0, sl);
+ // Calculate transform aligned to the circle
+ grad->xform[0] = r;
+ grad->xform[1] = 0;
+ grad->xform[2] = 0;
+ grad->xform[3] = r;
+ grad->xform[4] = cx;
+ grad->xform[5] = cy;
+ grad->fx = fx / r;
+ grad->fy = fy / r;
+ }
+
+ nsvg__xformMultiply(grad->xform, data->xform);
+ nsvg__xformMultiply(grad->xform, attr->xform);
+
+ grad->spread = data->spread;
+ memcpy(grad->stops, stops, nstops * sizeof(NSVGgradientStop));
+ grad->nstops = nstops;
+
+ *paintType = data->type;
+
+ return grad;
+}
+
+static float nsvg__getAverageScale(float *t) {
+ float sx = sqrtf(t[0] * t[0] + t[2] * t[2]);
+ float sy = sqrtf(t[1] * t[1] + t[3] * t[3]);
+ return (sx + sy) * 0.5f;
+}
+
+static void nsvg__getLocalBounds(float *bounds, NSVGshape *shape, float *xform) {
+ NSVGpath *path;
+ float curve[4 * 2], curveBounds[4];
+ int i, first = 1;
+ for (path = shape->paths; path != NULL; path = path->next) {
+ nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform);
+ for (i = 0; i < path->npts - 1; i += 3) {
+ nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i + 1) * 2], path->pts[(i + 1) * 2 + 1], xform);
+ nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i + 2) * 2], path->pts[(i + 2) * 2 + 1], xform);
+ nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i + 3) * 2], path->pts[(i + 3) * 2 + 1], xform);
+ nsvg__curveBounds(curveBounds, curve);
+ if (first) {
+ bounds[0] = curveBounds[0];
+ bounds[1] = curveBounds[1];
+ bounds[2] = curveBounds[2];
+ bounds[3] = curveBounds[3];
+ first = 0;
+ } else {
+ bounds[0] = nsvg__minf(bounds[0], curveBounds[0]);
+ bounds[1] = nsvg__minf(bounds[1], curveBounds[1]);
+ bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);
+ bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);
+ }
+ curve[0] = curve[6];
+ curve[1] = curve[7];
+ }
+ }
+}
+
+static void nsvg__addShape(NSVGparser *p) {
+ NSVGattrib *attr = nsvg__getAttr(p);
+ float scale = 1.0f;
+ NSVGshape *shape;
+ NSVGpath *path;
+ int i;
+
+ if (p->plist == NULL)
+ return;
+
+ shape = (NSVGshape *)malloc(sizeof(NSVGshape));
+ if (shape == NULL)
+ goto error;
+ memset(shape, 0, sizeof(NSVGshape));
+
+ memcpy(shape->id, attr->id, sizeof shape->id);
+ scale = nsvg__getAverageScale(attr->xform);
+ shape->strokeWidth = attr->strokeWidth * scale;
+ shape->strokeDashOffset = attr->strokeDashOffset * scale;
+ shape->strokeDashCount = (char)attr->strokeDashCount;
+ for (i = 0; i < attr->strokeDashCount; i++)
+ shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
+ shape->strokeLineJoin = attr->strokeLineJoin;
+ shape->strokeLineCap = attr->strokeLineCap;
+ shape->miterLimit = attr->miterLimit;
+ shape->fillRule = attr->fillRule;
+ shape->opacity = attr->opacity;
+
+ shape->paths = p->plist;
+ p->plist = NULL;
+
+ // Calculate shape bounds
+ shape->bounds[0] = shape->paths->bounds[0];
+ shape->bounds[1] = shape->paths->bounds[1];
+ shape->bounds[2] = shape->paths->bounds[2];
+ shape->bounds[3] = shape->paths->bounds[3];
+ for (path = shape->paths->next; path != NULL; path = path->next) {
+ shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
+ shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);
+ shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);
+ shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);
+ }
+
+ // Set fill
+ if (attr->hasFill == 0) {
+ shape->fill.type = NSVG_PAINT_NONE;
+ } else if (attr->hasFill == 1) {
+ shape->fill.type = NSVG_PAINT_COLOR;
+ shape->fill.color = attr->fillColor;
+ shape->fill.color |= (unsigned int)(attr->fillOpacity * 255) << 24;
+ } else if (attr->hasFill == 2) {
+ float inv[6], localBounds[4];
+ nsvg__xformInverse(inv, attr->xform);
+ nsvg__getLocalBounds(localBounds, shape, inv);
+ shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type);
+ if (shape->fill.gradient == NULL) {
+ shape->fill.type = NSVG_PAINT_NONE;
+ }
+ }
+
+ // Set stroke
+ if (attr->hasStroke == 0) {
+ shape->stroke.type = NSVG_PAINT_NONE;
+ } else if (attr->hasStroke == 1) {
+ shape->stroke.type = NSVG_PAINT_COLOR;
+ shape->stroke.color = attr->strokeColor;
+ shape->stroke.color |= (unsigned int)(attr->strokeOpacity * 255) << 24;
+ } else if (attr->hasStroke == 2) {
+ float inv[6], localBounds[4];
+ nsvg__xformInverse(inv, attr->xform);
+ nsvg__getLocalBounds(localBounds, shape, inv);
+ shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type);
+ if (shape->stroke.gradient == NULL)
+ shape->stroke.type = NSVG_PAINT_NONE;
+ }
+
+ // Set flags
+ shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00);
+
+ // Add to tail
+ if (p->image->shapes == NULL)
+ p->image->shapes = shape;
+ else
+ p->shapesTail->next = shape;
+ p->shapesTail = shape;
+
+ return;
error:
- if (shape) free(shape);
-}
-
-static void nsvg__addPath(NSVGparser* p, char closed)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- NSVGpath* path = NULL;
- float bounds[4];
- float* curve;
- int i;
-
- if (p->npts < 4)
- return;
-
- if (closed)
- nsvg__lineTo(p, p->pts[0], p->pts[1]);
-
- path = (NSVGpath*)malloc(sizeof(NSVGpath));
- if (path == NULL) goto error;
- memset(path, 0, sizeof(NSVGpath));
-
- path->pts = (float*)malloc(p->npts*2*sizeof(float));
- if (path->pts == NULL) goto error;
- path->closed = closed;
- path->npts = p->npts;
-
- // Transform path.
- for (i = 0; i < p->npts; ++i)
- nsvg__xformPoint(&path->pts[i*2], &path->pts[i*2+1], p->pts[i*2], p->pts[i*2+1], attr->xform);
-
- // Find bounds
- for (i = 0; i < path->npts-1; i += 3) {
- curve = &path->pts[i*2];
- nsvg__curveBounds(bounds, curve);
- if (i == 0) {
- path->bounds[0] = bounds[0];
- path->bounds[1] = bounds[1];
- path->bounds[2] = bounds[2];
- path->bounds[3] = bounds[3];
- } else {
- path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]);
- path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]);
- path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]);
- path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]);
- }
- }
-
- path->next = p->plist;
- p->plist = path;
-
- return;
+ if (shape)
+ free(shape);
+}
+
+static void nsvg__addPath(NSVGparser *p, char closed) {
+ NSVGattrib *attr = nsvg__getAttr(p);
+ NSVGpath *path = NULL;
+ float bounds[4];
+ float *curve;
+ int i;
+
+ if (p->npts < 4)
+ return;
+
+ if (closed)
+ nsvg__lineTo(p, p->pts[0], p->pts[1]);
+
+ path = (NSVGpath *)malloc(sizeof(NSVGpath));
+ if (path == NULL)
+ goto error;
+ memset(path, 0, sizeof(NSVGpath));
+
+ path->pts = (float *)malloc(p->npts * 2 * sizeof(float));
+ if (path->pts == NULL)
+ goto error;
+ path->closed = closed;
+ path->npts = p->npts;
+
+ // Transform path.
+ for (i = 0; i < p->npts; ++i)
+ nsvg__xformPoint(&path->pts[i * 2], &path->pts[i * 2 + 1], p->pts[i * 2], p->pts[i * 2 + 1], attr->xform);
+
+ // Find bounds
+ for (i = 0; i < path->npts - 1; i += 3) {
+ curve = &path->pts[i * 2];
+ nsvg__curveBounds(bounds, curve);
+ if (i == 0) {
+ path->bounds[0] = bounds[0];
+ path->bounds[1] = bounds[1];
+ path->bounds[2] = bounds[2];
+ path->bounds[3] = bounds[3];
+ } else {
+ path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]);
+ path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]);
+ path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]);
+ path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]);
+ }
+ }
+
+ path->next = p->plist;
+ p->plist = path;
+
+ return;
error:
- if (path != NULL) {
- if (path->pts != NULL) free(path->pts);
- free(path);
- }
+ if (path != NULL) {
+ if (path->pts != NULL)
+ free(path->pts);
+ free(path);
+ }
}
// We roll our own string to float because the std library one uses locale and messes things up.
-static double nsvg__atof(const char* s)
-{
- char* cur = (char*)s;
- char* end = NULL;
- double res = 0.0, sign = 1.0;
- long long intPart = 0, fracPart = 0;
- char hasIntPart = 0, hasFracPart = 0;
-
- // Parse optional sign
- if (*cur == '+') {
- cur++;
- } else if (*cur == '-') {
- sign = -1;
- cur++;
- }
-
- // Parse integer part
- if (nsvg__isdigit(*cur)) {
- // Parse digit sequence
- intPart = (double)strtoll(cur, &end, 10);
- if (cur != end) {
- res = (double)intPart;
- hasIntPart = 1;
- cur = end;
- }
- }
-
- // Parse fractional part.
- if (*cur == '.') {
- cur++; // Skip '.'
- if (nsvg__isdigit(*cur)) {
- // Parse digit sequence
- fracPart = strtoll(cur, &end, 10);
- if (cur != end) {
- res += (double)fracPart / pow(10.0, (double)(end - cur));
- hasFracPart = 1;
- cur = end;
- }
- }
- }
-
- // A valid number should have integer or fractional part.
- if (!hasIntPart && !hasFracPart)
- return 0.0;
-
- // Parse optional exponent
- if (*cur == 'e' || *cur == 'E') {
- int expPart = 0;
- cur++; // skip 'E'
- expPart = strtol(cur, &end, 10); // Parse digit sequence with sign
- if (cur != end) {
- res *= pow(10.0, (double)expPart);
- }
- }
-
- return res * sign;
-}
-
-
-static const char* nsvg__parseNumber(const char* s, char* it, const int size)
-{
- const int last = size-1;
- int i = 0;
-
- // sign
- if (*s == '-' || *s == '+') {
- if (i < last) it[i++] = *s;
- s++;
- }
- // integer part
- while (*s && nsvg__isdigit(*s)) {
- if (i < last) it[i++] = *s;
- s++;
- }
- if (*s == '.') {
- // decimal point
- if (i < last) it[i++] = *s;
- s++;
- // fraction part
- while (*s && nsvg__isdigit(*s)) {
- if (i < last) it[i++] = *s;
- s++;
- }
- }
- // exponent
- if (*s == 'e' || *s == 'E') {
- if (i < last) it[i++] = *s;
- s++;
- if (*s == '-' || *s == '+') {
- if (i < last) it[i++] = *s;
- s++;
- }
- while (*s && nsvg__isdigit(*s)) {
- if (i < last) it[i++] = *s;
- s++;
- }
- }
- it[i] = '\0';
-
- return s;
-}
-
-static const char* nsvg__getNextPathItem(const char* s, char* it)
-{
- it[0] = '\0';
- // Skip white spaces and commas
- while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
- if (!*s) return s;
- if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) {
- s = nsvg__parseNumber(s, it, 64);
- } else {
- // Parse command
- it[0] = *s++;
- it[1] = '\0';
- return s;
- }
-
- return s;
-}
-
-static unsigned int nsvg__parseColorHex(const char* str)
-{
- unsigned int c = 0, r = 0, g = 0, b = 0;
- int n = 0;
- str++; // skip #
- // Calculate number of characters.
- while(str[n] && !nsvg__isspace(str[n]))
- n++;
- if (n == 6) {
- sscanf(str, "%x", &c);
- } else if (n == 3) {
- sscanf(str, "%x", &c);
- c = (c&0xf) | ((c&0xf0) << 4) | ((c&0xf00) << 8);
- c |= c<<4;
- }
- r = (c >> 16) & 0xff;
- g = (c >> 8) & 0xff;
- b = c & 0xff;
- return NSVG_RGB(r,g,b);
-}
-
-static unsigned int nsvg__parseColorRGB(const char* str)
-{
- int r = -1, g = -1, b = -1;
- char s1[32]="", s2[32]="";
- sscanf(str + 4, "%d%[%%, \t]%d%[%%, \t]%d", &r, s1, &g, s2, &b);
- if (strchr(s1, '%')) {
- return NSVG_RGB((r*255)/100,(g*255)/100,(b*255)/100);
- } else {
- return NSVG_RGB(r,g,b);
- }
+static double nsvg__atof(const char *s) {
+ char *cur = (char *)s;
+ char *end = NULL;
+ double res = 0.0, sign = 1.0;
+ long long intPart = 0, fracPart = 0;
+ char hasIntPart = 0, hasFracPart = 0;
+
+ // Parse optional sign
+ if (*cur == '+') {
+ cur++;
+ } else if (*cur == '-') {
+ sign = -1;
+ cur++;
+ }
+
+ // Parse integer part
+ if (nsvg__isdigit(*cur)) {
+ // Parse digit sequence
+ intPart = (double)strtoll(cur, &end, 10);
+ if (cur != end) {
+ res = (double)intPart;
+ hasIntPart = 1;
+ cur = end;
+ }
+ }
+
+ // Parse fractional part.
+ if (*cur == '.') {
+ cur++; // Skip '.'
+ if (nsvg__isdigit(*cur)) {
+ // Parse digit sequence
+ fracPart = strtoll(cur, &end, 10);
+ if (cur != end) {
+ res += (double)fracPart / pow(10.0, (double)(end - cur));
+ hasFracPart = 1;
+ cur = end;
+ }
+ }
+ }
+
+ // A valid number should have integer or fractional part.
+ if (!hasIntPart && !hasFracPart)
+ return 0.0;
+
+ // Parse optional exponent
+ if (*cur == 'e' || *cur == 'E') {
+ int expPart = 0;
+ cur++; // skip 'E'
+ expPart = strtol(cur, &end, 10); // Parse digit sequence with sign
+ if (cur != end) {
+ res *= pow(10.0, (double)expPart);
+ }
+ }
+
+ return res * sign;
+}
+
+static const char *nsvg__parseNumber(const char *s, char *it, const int size) {
+ const int last = size - 1;
+ int i = 0;
+
+ // sign
+ if (*s == '-' || *s == '+') {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ // integer part
+ while (*s && nsvg__isdigit(*s)) {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ if (*s == '.') {
+ // decimal point
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ // fraction part
+ while (*s && nsvg__isdigit(*s)) {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ }
+ // exponent
+ if (*s == 'e' || *s == 'E') {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ if (*s == '-' || *s == '+') {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ while (*s && nsvg__isdigit(*s)) {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ }
+ it[i] = '\0';
+
+ return s;
+}
+
+static const char *nsvg__getNextPathItem(const char *s, char *it) {
+ it[0] = '\0';
+ // Skip white spaces and commas
+ while (*s && (nsvg__isspace(*s) || *s == ','))
+ s++;
+ if (!*s)
+ return s;
+ if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) {
+ s = nsvg__parseNumber(s, it, 64);
+ } else {
+ // Parse command
+ it[0] = *s++;
+ it[1] = '\0';
+ return s;
+ }
+
+ return s;
+}
+
+static unsigned int nsvg__parseColorHex(const char *str) {
+ unsigned int c = 0, r = 0, g = 0, b = 0;
+ int n = 0;
+ str++; // skip #
+ // Calculate number of characters.
+ while (str[n] && !nsvg__isspace(str[n]))
+ n++;
+ if (n == 6) {
+ sscanf(str, "%x", &c);
+ } else if (n == 3) {
+ sscanf(str, "%x", &c);
+ c = (c & 0xf) | ((c & 0xf0) << 4) | ((c & 0xf00) << 8);
+ c |= c << 4;
+ }
+ r = (c >> 16) & 0xff;
+ g = (c >> 8) & 0xff;
+ b = c & 0xff;
+ return NSVG_RGB(r, g, b);
+}
+
+static unsigned int nsvg__parseColorRGB(const char *str) {
+ int r = -1, g = -1, b = -1;
+ char s1[32] = "", s2[32] = "";
+ sscanf(str + 4, "%d%[%%, \t]%d%[%%, \t]%d", &r, s1, &g, s2, &b);
+ if (strchr(s1, '%')) {
+ return NSVG_RGB((r * 255) / 100, (g * 255) / 100, (b * 255) / 100);
+ } else {
+ return NSVG_RGB(r, g, b);
+ }
}
typedef struct NSVGNamedColor {
- const char* name;
- unsigned int color;
+ const char *name;
+ unsigned int color;
} NSVGNamedColor;
NSVGNamedColor nsvg__colors[] = {
- { "red", NSVG_RGB(255, 0, 0) },
- { "green", NSVG_RGB( 0, 128, 0) },
- { "blue", NSVG_RGB( 0, 0, 255) },
- { "yellow", NSVG_RGB(255, 255, 0) },
- { "cyan", NSVG_RGB( 0, 255, 255) },
- { "magenta", NSVG_RGB(255, 0, 255) },
- { "black", NSVG_RGB( 0, 0, 0) },
- { "grey", NSVG_RGB(128, 128, 128) },
- { "gray", NSVG_RGB(128, 128, 128) },
- { "white", NSVG_RGB(255, 255, 255) },
+ {"red", NSVG_RGB(255, 0, 0)},
+ {"green", NSVG_RGB(0, 128, 0)},
+ {"blue", NSVG_RGB(0, 0, 255)},
+ {"yellow", NSVG_RGB(255, 255, 0)},
+ {"cyan", NSVG_RGB(0, 255, 255)},
+ {"magenta", NSVG_RGB(255, 0, 255)},
+ {"black", NSVG_RGB(0, 0, 0)},
+ {"grey", NSVG_RGB(128, 128, 128)},
+ {"gray", NSVG_RGB(128, 128, 128)},
+ {"white", NSVG_RGB(255, 255, 255)},
#ifdef NANOSVG_ALL_COLOR_KEYWORDS
- { "aliceblue", NSVG_RGB(240, 248, 255) },
- { "antiquewhite", NSVG_RGB(250, 235, 215) },
- { "aqua", NSVG_RGB( 0, 255, 255) },
- { "aquamarine", NSVG_RGB(127, 255, 212) },
- { "azure", NSVG_RGB(240, 255, 255) },
- { "beige", NSVG_RGB(245, 245, 220) },
- { "bisque", NSVG_RGB(255, 228, 196) },
- { "blanchedalmond", NSVG_RGB(255, 235, 205) },
- { "blueviolet", NSVG_RGB(138, 43, 226) },
- { "brown", NSVG_RGB(165, 42, 42) },
- { "burlywood", NSVG_RGB(222, 184, 135) },
- { "cadetblue", NSVG_RGB( 95, 158, 160) },
- { "chartreuse", NSVG_RGB(127, 255, 0) },
- { "chocolate", NSVG_RGB(210, 105, 30) },
- { "coral", NSVG_RGB(255, 127, 80) },
- { "cornflowerblue", NSVG_RGB(100, 149, 237) },
- { "cornsilk", NSVG_RGB(255, 248, 220) },
- { "crimson", NSVG_RGB(220, 20, 60) },
- { "darkblue", NSVG_RGB( 0, 0, 139) },
- { "darkcyan", NSVG_RGB( 0, 139, 139) },
- { "darkgoldenrod", NSVG_RGB(184, 134, 11) },
- { "darkgray", NSVG_RGB(169, 169, 169) },
- { "darkgreen", NSVG_RGB( 0, 100, 0) },
- { "darkgrey", NSVG_RGB(169, 169, 169) },
- { "darkkhaki", NSVG_RGB(189, 183, 107) },
- { "darkmagenta", NSVG_RGB(139, 0, 139) },
- { "darkolivegreen", NSVG_RGB( 85, 107, 47) },
- { "darkorange", NSVG_RGB(255, 140, 0) },
- { "darkorchid", NSVG_RGB(153, 50, 204) },
- { "darkred", NSVG_RGB(139, 0, 0) },
- { "darksalmon", NSVG_RGB(233, 150, 122) },
- { "darkseagreen", NSVG_RGB(143, 188, 143) },
- { "darkslateblue", NSVG_RGB( 72, 61, 139) },
- { "darkslategray", NSVG_RGB( 47, 79, 79) },
- { "darkslategrey", NSVG_RGB( 47, 79, 79) },
- { "darkturquoise", NSVG_RGB( 0, 206, 209) },
- { "darkviolet", NSVG_RGB(148, 0, 211) },
- { "deeppink", NSVG_RGB(255, 20, 147) },
- { "deepskyblue", NSVG_RGB( 0, 191, 255) },
- { "dimgray", NSVG_RGB(105, 105, 105) },
- { "dimgrey", NSVG_RGB(105, 105, 105) },
- { "dodgerblue", NSVG_RGB( 30, 144, 255) },
- { "firebrick", NSVG_RGB(178, 34, 34) },
- { "floralwhite", NSVG_RGB(255, 250, 240) },
- { "forestgreen", NSVG_RGB( 34, 139, 34) },
- { "fuchsia", NSVG_RGB(255, 0, 255) },
- { "gainsboro", NSVG_RGB(220, 220, 220) },
- { "ghostwhite", NSVG_RGB(248, 248, 255) },
- { "gold", NSVG_RGB(255, 215, 0) },
- { "goldenrod", NSVG_RGB(218, 165, 32) },
- { "greenyellow", NSVG_RGB(173, 255, 47) },
- { "honeydew", NSVG_RGB(240, 255, 240) },
- { "hotpink", NSVG_RGB(255, 105, 180) },
- { "indianred", NSVG_RGB(205, 92, 92) },
- { "indigo", NSVG_RGB( 75, 0, 130) },
- { "ivory", NSVG_RGB(255, 255, 240) },
- { "khaki", NSVG_RGB(240, 230, 140) },
- { "lavender", NSVG_RGB(230, 230, 250) },
- { "lavenderblush", NSVG_RGB(255, 240, 245) },
- { "lawngreen", NSVG_RGB(124, 252, 0) },
- { "lemonchiffon", NSVG_RGB(255, 250, 205) },
- { "lightblue", NSVG_RGB(173, 216, 230) },
- { "lightcoral", NSVG_RGB(240, 128, 128) },
- { "lightcyan", NSVG_RGB(224, 255, 255) },
- { "lightgoldenrodyellow", NSVG_RGB(250, 250, 210) },
- { "lightgray", NSVG_RGB(211, 211, 211) },
- { "lightgreen", NSVG_RGB(144, 238, 144) },
- { "lightgrey", NSVG_RGB(211, 211, 211) },
- { "lightpink", NSVG_RGB(255, 182, 193) },
- { "lightsalmon", NSVG_RGB(255, 160, 122) },
- { "lightseagreen", NSVG_RGB( 32, 178, 170) },
- { "lightskyblue", NSVG_RGB(135, 206, 250) },
- { "lightslategray", NSVG_RGB(119, 136, 153) },
- { "lightslategrey", NSVG_RGB(119, 136, 153) },
- { "lightsteelblue", NSVG_RGB(176, 196, 222) },
- { "lightyellow", NSVG_RGB(255, 255, 224) },
- { "lime", NSVG_RGB( 0, 255, 0) },
- { "limegreen", NSVG_RGB( 50, 205, 50) },
- { "linen", NSVG_RGB(250, 240, 230) },
- { "maroon", NSVG_RGB(128, 0, 0) },
- { "mediumaquamarine", NSVG_RGB(102, 205, 170) },
- { "mediumblue", NSVG_RGB( 0, 0, 205) },
- { "mediumorchid", NSVG_RGB(186, 85, 211) },
- { "mediumpurple", NSVG_RGB(147, 112, 219) },
- { "mediumseagreen", NSVG_RGB( 60, 179, 113) },
- { "mediumslateblue", NSVG_RGB(123, 104, 238) },
- { "mediumspringgreen", NSVG_RGB( 0, 250, 154) },
- { "mediumturquoise", NSVG_RGB( 72, 209, 204) },
- { "mediumvioletred", NSVG_RGB(199, 21, 133) },
- { "midnightblue", NSVG_RGB( 25, 25, 112) },
- { "mintcream", NSVG_RGB(245, 255, 250) },
- { "mistyrose", NSVG_RGB(255, 228, 225) },
- { "moccasin", NSVG_RGB(255, 228, 181) },
- { "navajowhite", NSVG_RGB(255, 222, 173) },
- { "navy", NSVG_RGB( 0, 0, 128) },
- { "oldlace", NSVG_RGB(253, 245, 230) },
- { "olive", NSVG_RGB(128, 128, 0) },
- { "olivedrab", NSVG_RGB(107, 142, 35) },
- { "orange", NSVG_RGB(255, 165, 0) },
- { "orangered", NSVG_RGB(255, 69, 0) },
- { "orchid", NSVG_RGB(218, 112, 214) },
- { "palegoldenrod", NSVG_RGB(238, 232, 170) },
- { "palegreen", NSVG_RGB(152, 251, 152) },
- { "paleturquoise", NSVG_RGB(175, 238, 238) },
- { "palevioletred", NSVG_RGB(219, 112, 147) },
- { "papayawhip", NSVG_RGB(255, 239, 213) },
- { "peachpuff", NSVG_RGB(255, 218, 185) },
- { "peru", NSVG_RGB(205, 133, 63) },
- { "pink", NSVG_RGB(255, 192, 203) },
- { "plum", NSVG_RGB(221, 160, 221) },
- { "powderblue", NSVG_RGB(176, 224, 230) },
- { "purple", NSVG_RGB(128, 0, 128) },
- { "rosybrown", NSVG_RGB(188, 143, 143) },
- { "royalblue", NSVG_RGB( 65, 105, 225) },
- { "saddlebrown", NSVG_RGB(139, 69, 19) },
- { "salmon", NSVG_RGB(250, 128, 114) },
- { "sandybrown", NSVG_RGB(244, 164, 96) },
- { "seagreen", NSVG_RGB( 46, 139, 87) },
- { "seashell", NSVG_RGB(255, 245, 238) },
- { "sienna", NSVG_RGB(160, 82, 45) },
- { "silver", NSVG_RGB(192, 192, 192) },
- { "skyblue", NSVG_RGB(135, 206, 235) },
- { "slateblue", NSVG_RGB(106, 90, 205) },
- { "slategray", NSVG_RGB(112, 128, 144) },
- { "slategrey", NSVG_RGB(112, 128, 144) },
- { "snow", NSVG_RGB(255, 250, 250) },
- { "springgreen", NSVG_RGB( 0, 255, 127) },
- { "steelblue", NSVG_RGB( 70, 130, 180) },
- { "tan", NSVG_RGB(210, 180, 140) },
- { "teal", NSVG_RGB( 0, 128, 128) },
- { "thistle", NSVG_RGB(216, 191, 216) },
- { "tomato", NSVG_RGB(255, 99, 71) },
- { "turquoise", NSVG_RGB( 64, 224, 208) },
- { "violet", NSVG_RGB(238, 130, 238) },
- { "wheat", NSVG_RGB(245, 222, 179) },
- { "whitesmoke", NSVG_RGB(245, 245, 245) },
- { "yellowgreen", NSVG_RGB(154, 205, 50) },
+ {"aliceblue", NSVG_RGB(240, 248, 255)},
+ {"antiquewhite", NSVG_RGB(250, 235, 215)},
+ {"aqua", NSVG_RGB(0, 255, 255)},
+ {"aquamarine", NSVG_RGB(127, 255, 212)},
+ {"azure", NSVG_RGB(240, 255, 255)},
+ {"beige", NSVG_RGB(245, 245, 220)},
+ {"bisque", NSVG_RGB(255, 228, 196)},
+ {"blanchedalmond", NSVG_RGB(255, 235, 205)},
+ {"blueviolet", NSVG_RGB(138, 43, 226)},
+ {"brown", NSVG_RGB(165, 42, 42)},
+ {"burlywood", NSVG_RGB(222, 184, 135)},
+ {"cadetblue", NSVG_RGB(95, 158, 160)},
+ {"chartreuse", NSVG_RGB(127, 255, 0)},
+ {"chocolate", NSVG_RGB(210, 105, 30)},
+ {"coral", NSVG_RGB(255, 127, 80)},
+ {"cornflowerblue", NSVG_RGB(100, 149, 237)},
+ {"cornsilk", NSVG_RGB(255, 248, 220)},
+ {"crimson", NSVG_RGB(220, 20, 60)},
+ {"darkblue", NSVG_RGB(0, 0, 139)},
+ {"darkcyan", NSVG_RGB(0, 139, 139)},
+ {"darkgoldenrod", NSVG_RGB(184, 134, 11)},
+ {"darkgray", NSVG_RGB(169, 169, 169)},
+ {"darkgreen", NSVG_RGB(0, 100, 0)},
+ {"darkgrey", NSVG_RGB(169, 169, 169)},
+ {"darkkhaki", NSVG_RGB(189, 183, 107)},
+ {"darkmagenta", NSVG_RGB(139, 0, 139)},
+ {"darkolivegreen", NSVG_RGB(85, 107, 47)},
+ {"darkorange", NSVG_RGB(255, 140, 0)},
+ {"darkorchid", NSVG_RGB(153, 50, 204)},
+ {"darkred", NSVG_RGB(139, 0, 0)},
+ {"darksalmon", NSVG_RGB(233, 150, 122)},
+ {"darkseagreen", NSVG_RGB(143, 188, 143)},
+ {"darkslateblue", NSVG_RGB(72, 61, 139)},
+ {"darkslategray", NSVG_RGB(47, 79, 79)},
+ {"darkslategrey", NSVG_RGB(47, 79, 79)},
+ {"darkturquoise", NSVG_RGB(0, 206, 209)},
+ {"darkviolet", NSVG_RGB(148, 0, 211)},
+ {"deeppink", NSVG_RGB(255, 20, 147)},
+ {"deepskyblue", NSVG_RGB(0, 191, 255)},
+ {"dimgray", NSVG_RGB(105, 105, 105)},
+ {"dimgrey", NSVG_RGB(105, 105, 105)},
+ {"dodgerblue", NSVG_RGB(30, 144, 255)},
+ {"firebrick", NSVG_RGB(178, 34, 34)},
+ {"floralwhite", NSVG_RGB(255, 250, 240)},
+ {"forestgreen", NSVG_RGB(34, 139, 34)},
+ {"fuchsia", NSVG_RGB(255, 0, 255)},
+ {"gainsboro", NSVG_RGB(220, 220, 220)},
+ {"ghostwhite", NSVG_RGB(248, 248, 255)},
+ {"gold", NSVG_RGB(255, 215, 0)},
+ {"goldenrod", NSVG_RGB(218, 165, 32)},
+ {"greenyellow", NSVG_RGB(173, 255, 47)},
+ {"honeydew", NSVG_RGB(240, 255, 240)},
+ {"hotpink", NSVG_RGB(255, 105, 180)},
+ {"indianred", NSVG_RGB(205, 92, 92)},
+ {"indigo", NSVG_RGB(75, 0, 130)},
+ {"ivory", NSVG_RGB(255, 255, 240)},
+ {"khaki", NSVG_RGB(240, 230, 140)},
+ {"lavender", NSVG_RGB(230, 230, 250)},
+ {"lavenderblush", NSVG_RGB(255, 240, 245)},
+ {"lawngreen", NSVG_RGB(124, 252, 0)},
+ {"lemonchiffon", NSVG_RGB(255, 250, 205)},
+ {"lightblue", NSVG_RGB(173, 216, 230)},
+ {"lightcoral", NSVG_RGB(240, 128, 128)},
+ {"lightcyan", NSVG_RGB(224, 255, 255)},
+ {"lightgoldenrodyellow", NSVG_RGB(250, 250, 210)},
+ {"lightgray", NSVG_RGB(211, 211, 211)},
+ {"lightgreen", NSVG_RGB(144, 238, 144)},
+ {"lightgrey", NSVG_RGB(211, 211, 211)},
+ {"lightpink", NSVG_RGB(255, 182, 193)},
+ {"lightsalmon", NSVG_RGB(255, 160, 122)},
+ {"lightseagreen", NSVG_RGB(32, 178, 170)},
+ {"lightskyblue", NSVG_RGB(135, 206, 250)},
+ {"lightslategray", NSVG_RGB(119, 136, 153)},
+ {"lightslategrey", NSVG_RGB(119, 136, 153)},
+ {"lightsteelblue", NSVG_RGB(176, 196, 222)},
+ {"lightyellow", NSVG_RGB(255, 255, 224)},
+ {"lime", NSVG_RGB(0, 255, 0)},
+ {"limegreen", NSVG_RGB(50, 205, 50)},
+ {"linen", NSVG_RGB(250, 240, 230)},
+ {"maroon", NSVG_RGB(128, 0, 0)},
+ {"mediumaquamarine", NSVG_RGB(102, 205, 170)},
+ {"mediumblue", NSVG_RGB(0, 0, 205)},
+ {"mediumorchid", NSVG_RGB(186, 85, 211)},
+ {"mediumpurple", NSVG_RGB(147, 112, 219)},
+ {"mediumseagreen", NSVG_RGB(60, 179, 113)},
+ {"mediumslateblue", NSVG_RGB(123, 104, 238)},
+ {"mediumspringgreen", NSVG_RGB(0, 250, 154)},
+ {"mediumturquoise", NSVG_RGB(72, 209, 204)},
+ {"mediumvioletred", NSVG_RGB(199, 21, 133)},
+ {"midnightblue", NSVG_RGB(25, 25, 112)},
+ {"mintcream", NSVG_RGB(245, 255, 250)},
+ {"mistyrose", NSVG_RGB(255, 228, 225)},
+ {"moccasin", NSVG_RGB(255, 228, 181)},
+ {"navajowhite", NSVG_RGB(255, 222, 173)},
+ {"navy", NSVG_RGB(0, 0, 128)},
+ {"oldlace", NSVG_RGB(253, 245, 230)},
+ {"olive", NSVG_RGB(128, 128, 0)},
+ {"olivedrab", NSVG_RGB(107, 142, 35)},
+ {"orange", NSVG_RGB(255, 165, 0)},
+ {"orangered", NSVG_RGB(255, 69, 0)},
+ {"orchid", NSVG_RGB(218, 112, 214)},
+ {"palegoldenrod", NSVG_RGB(238, 232, 170)},
+ {"palegreen", NSVG_RGB(152, 251, 152)},
+ {"paleturquoise", NSVG_RGB(175, 238, 238)},
+ {"palevioletred", NSVG_RGB(219, 112, 147)},
+ {"papayawhip", NSVG_RGB(255, 239, 213)},
+ {"peachpuff", NSVG_RGB(255, 218, 185)},
+ {"peru", NSVG_RGB(205, 133, 63)},
+ {"pink", NSVG_RGB(255, 192, 203)},
+ {"plum", NSVG_RGB(221, 160, 221)},
+ {"powderblue", NSVG_RGB(176, 224, 230)},
+ {"purple", NSVG_RGB(128, 0, 128)},
+ {"rosybrown", NSVG_RGB(188, 143, 143)},
+ {"royalblue", NSVG_RGB(65, 105, 225)},
+ {"saddlebrown", NSVG_RGB(139, 69, 19)},
+ {"salmon", NSVG_RGB(250, 128, 114)},
+ {"sandybrown", NSVG_RGB(244, 164, 96)},
+ {"seagreen", NSVG_RGB(46, 139, 87)},
+ {"seashell", NSVG_RGB(255, 245, 238)},
+ {"sienna", NSVG_RGB(160, 82, 45)},
+ {"silver", NSVG_RGB(192, 192, 192)},
+ {"skyblue", NSVG_RGB(135, 206, 235)},
+ {"slateblue", NSVG_RGB(106, 90, 205)},
+ {"slategray", NSVG_RGB(112, 128, 144)},
+ {"slategrey", NSVG_RGB(112, 128, 144)},
+ {"snow", NSVG_RGB(255, 250, 250)},
+ {"springgreen", NSVG_RGB(0, 255, 127)},
+ {"steelblue", NSVG_RGB(70, 130, 180)},
+ {"tan", NSVG_RGB(210, 180, 140)},
+ {"teal", NSVG_RGB(0, 128, 128)},
+ {"thistle", NSVG_RGB(216, 191, 216)},
+ {"tomato", NSVG_RGB(255, 99, 71)},
+ {"turquoise", NSVG_RGB(64, 224, 208)},
+ {"violet", NSVG_RGB(238, 130, 238)},
+ {"wheat", NSVG_RGB(245, 222, 179)},
+ {"whitesmoke", NSVG_RGB(245, 245, 245)},
+ {"yellowgreen", NSVG_RGB(154, 205, 50)},
#endif
};
-static unsigned int nsvg__parseColorName(const char* str)
-{
- int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);
-
- for (i = 0; i < ncolors; i++) {
- if (strcmp(nsvg__colors[i].name, str) == 0) {
- return nsvg__colors[i].color;
- }
- }
-
- return NSVG_RGB(128, 128, 128);
-}
-
-static unsigned int nsvg__parseColor(const char* str)
-{
- size_t len = 0;
- while(*str == ' ') ++str;
- len = strlen(str);
- if (len >= 1 && *str == '#')
- return nsvg__parseColorHex(str);
- else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(')
- return nsvg__parseColorRGB(str);
- return nsvg__parseColorName(str);
-}
-
-static float nsvg__parseOpacity(const char* str)
-{
- float val = 0;
- sscanf(str, "%f", &val);
- if (val < 0.0f) val = 0.0f;
- if (val > 1.0f) val = 1.0f;
- return val;
-}
-
-static float nsvg__parseMiterLimit(const char* str)
-{
- float val = 0;
- sscanf(str, "%f", &val);
- if (val < 0.0f) val = 0.0f;
- return val;
-}
-
-static int nsvg__parseUnits(const char* units)
-{
- if (units[0] == 'p' && units[1] == 'x')
- return NSVG_UNITS_PX;
- else if (units[0] == 'p' && units[1] == 't')
- return NSVG_UNITS_PT;
- else if (units[0] == 'p' && units[1] == 'c')
- return NSVG_UNITS_PC;
- else if (units[0] == 'm' && units[1] == 'm')
- return NSVG_UNITS_MM;
- else if (units[0] == 'c' && units[1] == 'm')
- return NSVG_UNITS_CM;
- else if (units[0] == 'i' && units[1] == 'n')
- return NSVG_UNITS_IN;
- else if (units[0] == '%')
- return NSVG_UNITS_PERCENT;
- else if (units[0] == 'e' && units[1] == 'm')
- return NSVG_UNITS_EM;
- else if (units[0] == 'e' && units[1] == 'x')
- return NSVG_UNITS_EX;
- return NSVG_UNITS_USER;
-}
-
-static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str)
-{
- NSVGcoordinate coord = {0, NSVG_UNITS_USER};
- char units[32]="";
- sscanf(str, "%f%31s", &coord.value, units);
- coord.units = nsvg__parseUnits(units);
- return coord;
-}
-
-static NSVGcoordinate nsvg__coord(float v, int units)
-{
- NSVGcoordinate coord = {v, units};
- return coord;
-}
-
-static float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length)
-{
- NSVGcoordinate coord = nsvg__parseCoordinateRaw(str);
- return nsvg__convertToPixels(p, coord, orig, length);
-}
-
-static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na)
-{
- const char* end;
- const char* ptr;
- char it[64];
-
- *na = 0;
- ptr = str;
- while (*ptr && *ptr != '(') ++ptr;
- if (*ptr == 0)
- return 1;
- end = ptr;
- while (*end && *end != ')') ++end;
- if (*end == 0)
- return 1;
-
- while (ptr < end) {
- if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) {
- if (*na >= maxNa) return 0;
- ptr = nsvg__parseNumber(ptr, it, 64);
- args[(*na)++] = (float)nsvg__atof(it);
- } else {
- ++ptr;
- }
- }
- return (int)(end - str);
-}
-
-
-static int nsvg__parseMatrix(float* xform, const char* str)
-{
- float t[6];
- int na = 0;
- int len = nsvg__parseTransformArgs(str, t, 6, &na);
- if (na != 6) return len;
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseTranslate(float* xform, const char* str)
-{
- float args[2];
- float t[6];
- int na = 0;
- int len = nsvg__parseTransformArgs(str, args, 2, &na);
- if (na == 1) args[1] = 0.0;
-
- nsvg__xformSetTranslation(t, args[0], args[1]);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseScale(float* xform, const char* str)
-{
- float args[2];
- int na = 0;
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 2, &na);
- if (na == 1) args[1] = args[0];
- nsvg__xformSetScale(t, args[0], args[1]);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseSkewX(float* xform, const char* str)
-{
- float args[1];
- int na = 0;
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 1, &na);
- nsvg__xformSetSkewX(t, args[0]/180.0f*NSVG_PI);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseSkewY(float* xform, const char* str)
-{
- float args[1];
- int na = 0;
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 1, &na);
- nsvg__xformSetSkewY(t, args[0]/180.0f*NSVG_PI);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseRotate(float* xform, const char* str)
-{
- float args[3];
- int na = 0;
- float m[6];
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 3, &na);
- if (na == 1)
- args[1] = args[2] = 0.0f;
- nsvg__xformIdentity(m);
-
- if (na > 1) {
- nsvg__xformSetTranslation(t, -args[1], -args[2]);
- nsvg__xformMultiply(m, t);
- }
-
- nsvg__xformSetRotation(t, args[0]/180.0f*NSVG_PI);
- nsvg__xformMultiply(m, t);
-
- if (na > 1) {
- nsvg__xformSetTranslation(t, args[1], args[2]);
- nsvg__xformMultiply(m, t);
- }
-
- memcpy(xform, m, sizeof(float)*6);
-
- return len;
-}
-
-static void nsvg__parseTransform(float* xform, const char* str)
-{
- float t[6];
- nsvg__xformIdentity(xform);
- while (*str)
- {
- if (strncmp(str, "matrix", 6) == 0)
- str += nsvg__parseMatrix(t, str);
- else if (strncmp(str, "translate", 9) == 0)
- str += nsvg__parseTranslate(t, str);
- else if (strncmp(str, "scale", 5) == 0)
- str += nsvg__parseScale(t, str);
- else if (strncmp(str, "rotate", 6) == 0)
- str += nsvg__parseRotate(t, str);
- else if (strncmp(str, "skewX", 5) == 0)
- str += nsvg__parseSkewX(t, str);
- else if (strncmp(str, "skewY", 5) == 0)
- str += nsvg__parseSkewY(t, str);
- else{
- ++str;
- continue;
- }
-
- nsvg__xformPremultiply(xform, t);
- }
-}
-
-static void nsvg__parseUrl(char* id, const char* str)
-{
- int i = 0;
- str += 4; // "url(";
- if (*str == '#')
- str++;
- while (i < 63 && *str != ')') {
- id[i] = *str++;
- i++;
- }
- id[i] = '\0';
-}
-
-static char nsvg__parseLineCap(const char* str)
-{
- if (strcmp(str, "butt") == 0)
- return NSVG_CAP_BUTT;
- else if (strcmp(str, "round") == 0)
- return NSVG_CAP_ROUND;
- else if (strcmp(str, "square") == 0)
- return NSVG_CAP_SQUARE;
- // TODO: handle inherit.
- return NSVG_CAP_BUTT;
-}
-
-static char nsvg__parseLineJoin(const char* str)
-{
- if (strcmp(str, "miter") == 0)
- return NSVG_JOIN_MITER;
- else if (strcmp(str, "round") == 0)
- return NSVG_JOIN_ROUND;
- else if (strcmp(str, "bevel") == 0)
- return NSVG_JOIN_BEVEL;
- // TODO: handle inherit.
- return NSVG_JOIN_MITER;
-}
-
-static char nsvg__parseFillRule(const char* str)
-{
- if (strcmp(str, "nonzero") == 0)
- return NSVG_FILLRULE_NONZERO;
- else if (strcmp(str, "evenodd") == 0)
- return NSVG_FILLRULE_EVENODD;
- // TODO: handle inherit.
- return NSVG_FILLRULE_NONZERO;
-}
-
-static const char* nsvg__getNextDashItem(const char* s, char* it)
-{
- int n = 0;
- it[0] = '\0';
- // Skip white spaces and commas
- while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
- // Advance until whitespace, comma or end.
- while (*s && (!nsvg__isspace(*s) && *s != ',')) {
- if (n < 63)
- it[n++] = *s;
- s++;
- }
- it[n++] = '\0';
- return s;
-}
-
-static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray)
-{
- char item[64];
- int count = 0, i;
- float sum = 0.0f;
-
- // Handle "none"
- if (str[0] == 'n')
- return 0;
-
- // Parse dashes
- while (*str) {
- str = nsvg__getNextDashItem(str, item);
- if (!*item) break;
- if (count < NSVG_MAX_DASHES)
- strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p)));
- }
-
- for (i = 0; i < count; i++)
- sum += strokeDashArray[i];
- if (sum <= 1e-6f)
- count = 0;
-
- return count;
-}
-
-static void nsvg__parseStyle(NSVGparser* p, const char* str);
-
-static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value)
-{
- float xform[6];
- NSVGattrib* attr = nsvg__getAttr(p);
- if (!attr) return 0;
-
- if (strcmp(name, "style") == 0) {
- nsvg__parseStyle(p, value);
- } else if (strcmp(name, "display") == 0) {
- if (strcmp(value, "none") == 0)
- attr->visible = 0;
- // Don't reset ->visible on display:inline, one display:none hides the whole subtree
-
- } else if (strcmp(name, "fill") == 0) {
- if (strcmp(value, "none") == 0) {
- attr->hasFill = 0;
- } else if (strncmp(value, "url(", 4) == 0) {
- attr->hasFill = 2;
- nsvg__parseUrl(attr->fillGradient, value);
- } else {
- attr->hasFill = 1;
- attr->fillColor = nsvg__parseColor(value);
- }
- } else if (strcmp(name, "opacity") == 0) {
- attr->opacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "fill-opacity") == 0) {
- attr->fillOpacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "stroke") == 0) {
- if (strcmp(value, "none") == 0) {
- attr->hasStroke = 0;
- } else if (strncmp(value, "url(", 4) == 0) {
- attr->hasStroke = 2;
- nsvg__parseUrl(attr->strokeGradient, value);
- } else {
- attr->hasStroke = 1;
- attr->strokeColor = nsvg__parseColor(value);
- }
- } else if (strcmp(name, "stroke-width") == 0) {
- attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
- } else if (strcmp(name, "stroke-dasharray") == 0) {
- attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray);
- } else if (strcmp(name, "stroke-dashoffset") == 0) {
- attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
- } else if (strcmp(name, "stroke-opacity") == 0) {
- attr->strokeOpacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "stroke-linecap") == 0) {
- attr->strokeLineCap = nsvg__parseLineCap(value);
- } else if (strcmp(name, "stroke-linejoin") == 0) {
- attr->strokeLineJoin = nsvg__parseLineJoin(value);
- } else if (strcmp(name, "stroke-miterlimit") == 0) {
- attr->miterLimit = nsvg__parseMiterLimit(value);
- } else if (strcmp(name, "fill-rule") == 0) {
- attr->fillRule = nsvg__parseFillRule(value);
- } else if (strcmp(name, "font-size") == 0) {
- attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
- } else if (strcmp(name, "transform") == 0) {
- nsvg__parseTransform(xform, value);
- nsvg__xformPremultiply(attr->xform, xform);
- } else if (strcmp(name, "stop-color") == 0) {
- attr->stopColor = nsvg__parseColor(value);
- } else if (strcmp(name, "stop-opacity") == 0) {
- attr->stopOpacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "offset") == 0) {
- attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);
- } else if (strcmp(name, "id") == 0) {
- strncpy(attr->id, value, 63);
- attr->id[63] = '\0';
- } else {
- return 0;
- }
- return 1;
-}
-
-static int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end)
-{
- const char* str;
- const char* val;
- char name[512];
- char value[512];
- int n;
-
- str = start;
- while (str < end && *str != ':') ++str;
-
- val = str;
-
- // Right Trim
- while (str > start && (*str == ':' || nsvg__isspace(*str))) --str;
- ++str;
-
- n = (int)(str - start);
- if (n > 511) n = 511;
- if (n) memcpy(name, start, n);
- name[n] = 0;
-
- while (val < end && (*val == ':' || nsvg__isspace(*val))) ++val;
-
- n = (int)(end - val);
- if (n > 511) n = 511;
- if (n) memcpy(value, val, n);
- value[n] = 0;
-
- return nsvg__parseAttr(p, name, value);
-}
-
-static void nsvg__parseStyle(NSVGparser* p, const char* str)
-{
- const char* start;
- const char* end;
-
- while (*str) {
- // Left Trim
- while(*str && nsvg__isspace(*str)) ++str;
- start = str;
- while(*str && *str != ';') ++str;
- end = str;
-
- // Right Trim
- while (end > start && (*end == ';' || nsvg__isspace(*end))) --end;
- ++end;
-
- nsvg__parseNameValue(p, start, end);
- if (*str) ++str;
- }
-}
-
-static void nsvg__parseAttribs(NSVGparser* p, const char** attr)
-{
- int i;
- for (i = 0; attr[i]; i += 2)
- {
- if (strcmp(attr[i], "style") == 0)
- nsvg__parseStyle(p, attr[i + 1]);
- else
- nsvg__parseAttr(p, attr[i], attr[i + 1]);
- }
-}
-
-static int nsvg__getArgsPerElement(char cmd)
-{
- switch (cmd) {
- case 'v':
- case 'V':
- case 'h':
- case 'H':
- return 1;
- case 'm':
- case 'M':
- case 'l':
- case 'L':
- case 't':
- case 'T':
- return 2;
- case 'q':
- case 'Q':
- case 's':
- case 'S':
- return 4;
- case 'c':
- case 'C':
- return 6;
- case 'a':
- case 'A':
- return 7;
- }
- return 0;
-}
-
-static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel) {
- *cpx += args[0];
- *cpy += args[1];
- } else {
- *cpx = args[0];
- *cpy = args[1];
- }
- nsvg__moveTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel) {
- *cpx += args[0];
- *cpy += args[1];
- } else {
- *cpx = args[0];
- *cpy = args[1];
- }
- nsvg__lineTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel)
- *cpx += args[0];
- else
- *cpx = args[0];
- nsvg__lineTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel)
- *cpy += args[0];
- else
- *cpy = args[0];
- nsvg__lineTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x2, y2, cx1, cy1, cx2, cy2;
-
- if (rel) {
- cx1 = *cpx + args[0];
- cy1 = *cpy + args[1];
- cx2 = *cpx + args[2];
- cy2 = *cpy + args[3];
- x2 = *cpx + args[4];
- y2 = *cpy + args[5];
- } else {
- cx1 = args[0];
- cy1 = args[1];
- cx2 = args[2];
- cy2 = args[3];
- x2 = args[4];
- y2 = args[5];
- }
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx2;
- *cpy2 = cy2;
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x1, y1, x2, y2, cx1, cy1, cx2, cy2;
-
- x1 = *cpx;
- y1 = *cpy;
- if (rel) {
- cx2 = *cpx + args[0];
- cy2 = *cpy + args[1];
- x2 = *cpx + args[2];
- y2 = *cpy + args[3];
- } else {
- cx2 = args[0];
- cy2 = args[1];
- x2 = args[2];
- y2 = args[3];
- }
-
- cx1 = 2*x1 - *cpx2;
- cy1 = 2*y1 - *cpy2;
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx2;
- *cpy2 = cy2;
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x1, y1, x2, y2, cx, cy;
- float cx1, cy1, cx2, cy2;
-
- x1 = *cpx;
- y1 = *cpy;
- if (rel) {
- cx = *cpx + args[0];
- cy = *cpy + args[1];
- x2 = *cpx + args[2];
- y2 = *cpy + args[3];
- } else {
- cx = args[0];
- cy = args[1];
- x2 = args[2];
- y2 = args[3];
- }
-
- // Convert to cubic bezier
- cx1 = x1 + 2.0f/3.0f*(cx - x1);
- cy1 = y1 + 2.0f/3.0f*(cy - y1);
- cx2 = x2 + 2.0f/3.0f*(cx - x2);
- cy2 = y2 + 2.0f/3.0f*(cy - y2);
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx;
- *cpy2 = cy;
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x1, y1, x2, y2, cx, cy;
- float cx1, cy1, cx2, cy2;
-
- x1 = *cpx;
- y1 = *cpy;
- if (rel) {
- x2 = *cpx + args[0];
- y2 = *cpy + args[1];
- } else {
- x2 = args[0];
- y2 = args[1];
- }
-
- cx = 2*x1 - *cpx2;
- cy = 2*y1 - *cpy2;
-
- // Convert to cubix bezier
- cx1 = x1 + 2.0f/3.0f*(cx - x1);
- cy1 = y1 + 2.0f/3.0f*(cy - y1);
- cx2 = x2 + 2.0f/3.0f*(cx - x2);
- cy2 = y2 + 2.0f/3.0f*(cy - y2);
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx;
- *cpy2 = cy;
- *cpx = x2;
- *cpy = y2;
-}
-
-static float nsvg__sqr(float x) { return x*x; }
-static float nsvg__vmag(float x, float y) { return sqrtf(x*x + y*y); }
-
-static float nsvg__vecrat(float ux, float uy, float vx, float vy)
-{
- return (ux*vx + uy*vy) / (nsvg__vmag(ux,uy) * nsvg__vmag(vx,vy));
-}
-
-static float nsvg__vecang(float ux, float uy, float vx, float vy)
-{
- float r = nsvg__vecrat(ux,uy, vx,vy);
- if (r < -1.0f) r = -1.0f;
- if (r > 1.0f) r = 1.0f;
- return ((ux*vy < uy*vx) ? -1.0f : 1.0f) * acosf(r);
-}
-
-static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- // Ported from canvg (https://code.google.com/p/canvg/)
- float rx, ry, rotx;
- float x1, y1, x2, y2, cx, cy, dx, dy, d;
- float x1p, y1p, cxp, cyp, s, sa, sb;
- float ux, uy, vx, vy, a1, da;
- float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6];
- float sinrx, cosrx;
- int fa, fs;
- int i, ndivs;
- float hda, kappa;
-
- rx = fabsf(args[0]); // y radius
- ry = fabsf(args[1]); // x radius
- rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle
- fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc
- fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction
- x1 = *cpx; // start point
- y1 = *cpy;
- if (rel) { // end point
- x2 = *cpx + args[5];
- y2 = *cpy + args[6];
- } else {
- x2 = args[5];
- y2 = args[6];
- }
-
- dx = x1 - x2;
- dy = y1 - y2;
- d = sqrtf(dx*dx + dy*dy);
- if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) {
- // The arc degenerates to a line
- nsvg__lineTo(p, x2, y2);
- *cpx = x2;
- *cpy = y2;
- return;
- }
-
- sinrx = sinf(rotx);
- cosrx = cosf(rotx);
-
- // Convert to center point parameterization.
- // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
- // 1) Compute x1', y1'
- x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f;
- y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f;
- d = nsvg__sqr(x1p)/nsvg__sqr(rx) + nsvg__sqr(y1p)/nsvg__sqr(ry);
- if (d > 1) {
- d = sqrtf(d);
- rx *= d;
- ry *= d;
- }
- // 2) Compute cx', cy'
- s = 0.0f;
- sa = nsvg__sqr(rx)*nsvg__sqr(ry) - nsvg__sqr(rx)*nsvg__sqr(y1p) - nsvg__sqr(ry)*nsvg__sqr(x1p);
- sb = nsvg__sqr(rx)*nsvg__sqr(y1p) + nsvg__sqr(ry)*nsvg__sqr(x1p);
- if (sa < 0.0f) sa = 0.0f;
- if (sb > 0.0f)
- s = sqrtf(sa / sb);
- if (fa == fs)
- s = -s;
- cxp = s * rx * y1p / ry;
- cyp = s * -ry * x1p / rx;
-
- // 3) Compute cx,cy from cx',cy'
- cx = (x1 + x2)/2.0f + cosrx*cxp - sinrx*cyp;
- cy = (y1 + y2)/2.0f + sinrx*cxp + cosrx*cyp;
-
- // 4) Calculate theta1, and delta theta.
- ux = (x1p - cxp) / rx;
- uy = (y1p - cyp) / ry;
- vx = (-x1p - cxp) / rx;
- vy = (-y1p - cyp) / ry;
- a1 = nsvg__vecang(1.0f,0.0f, ux,uy); // Initial angle
- da = nsvg__vecang(ux,uy, vx,vy); // Delta angle
-
-// if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI;
-// if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0;
-
- if (fs == 0 && da > 0)
- da -= 2 * NSVG_PI;
- else if (fs == 1 && da < 0)
- da += 2 * NSVG_PI;
-
- // Approximate the arc using cubic spline segments.
- t[0] = cosrx; t[1] = sinrx;
- t[2] = -sinrx; t[3] = cosrx;
- t[4] = cx; t[5] = cy;
-
- // Split arc into max 90 degree segments.
- // The loop assumes an iteration per end point (including start and end), this +1.
- ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f);
- hda = (da / (float)ndivs) / 2.0f;
- kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda));
- if (da < 0.0f)
- kappa = -kappa;
-
- for (i = 0; i <= ndivs; i++) {
- a = a1 + da * ((float)i/(float)ndivs);
- dx = cosf(a);
- dy = sinf(a);
- nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); // position
- nsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); // tangent
- if (i > 0)
- nsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y);
- px = x;
- py = y;
- ptanx = tanx;
- ptany = tany;
- }
-
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__parsePath(NSVGparser* p, const char** attr)
-{
- const char* s = NULL;
- char cmd = '\0';
- float args[10];
- int nargs;
- int rargs = 0;
- float cpx, cpy, cpx2, cpy2;
- const char* tmp[4];
- char closedFlag;
- int i;
- char item[64];
-
- for (i = 0; attr[i]; i += 2) {
- if (strcmp(attr[i], "d") == 0) {
- s = attr[i + 1];
- } else {
- tmp[0] = attr[i];
- tmp[1] = attr[i + 1];
- tmp[2] = 0;
- tmp[3] = 0;
- nsvg__parseAttribs(p, tmp);
- }
- }
-
- if (s) {
- nsvg__resetPath(p);
- cpx = 0; cpy = 0;
- cpx2 = 0; cpy2 = 0;
- closedFlag = 0;
- nargs = 0;
-
- while (*s) {
- s = nsvg__getNextPathItem(s, item);
- if (!*item) break;
- if (nsvg__isnum(item[0])) {
- if (nargs < 10)
- args[nargs++] = (float)nsvg__atof(item);
- if (nargs >= rargs) {
- switch (cmd) {
- case 'm':
- case 'M':
- nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);
- // Moveto can be followed by multiple coordinate pairs,
- // which should be treated as linetos.
- cmd = (cmd == 'm') ? 'l' : 'L';
- rargs = nsvg__getArgsPerElement(cmd);
- cpx2 = cpx; cpy2 = cpy;
- break;
- case 'l':
- case 'L':
- nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- case 'H':
- case 'h':
- nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- case 'V':
- case 'v':
- nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- case 'C':
- case 'c':
- nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
- break;
- case 'S':
- case 's':
- nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
- break;
- case 'Q':
- case 'q':
- nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
- break;
- case 'T':
- case 't':
- nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0);
- break;
- case 'A':
- case 'a':
- nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- default:
- if (nargs >= 2) {
- cpx = args[nargs-2];
- cpy = args[nargs-1];
- cpx2 = cpx; cpy2 = cpy;
- }
- break;
- }
- nargs = 0;
- }
- } else {
- cmd = item[0];
- rargs = nsvg__getArgsPerElement(cmd);
- if (cmd == 'M' || cmd == 'm') {
- // Commit path.
- if (p->npts > 0)
- nsvg__addPath(p, closedFlag);
- // Start new subpath.
- nsvg__resetPath(p);
- closedFlag = 0;
- nargs = 0;
- } else if (cmd == 'Z' || cmd == 'z') {
- closedFlag = 1;
- // Commit path.
- if (p->npts > 0) {
- // Move current point to first point
- cpx = p->pts[0];
- cpy = p->pts[1];
- cpx2 = cpx; cpy2 = cpy;
- nsvg__addPath(p, closedFlag);
- }
- // Start new subpath.
- nsvg__resetPath(p);
- nsvg__moveTo(p, cpx, cpy);
- closedFlag = 0;
- nargs = 0;
- }
- }
- }
- // Commit path.
- if (p->npts)
- nsvg__addPath(p, closedFlag);
- }
-
- nsvg__addShape(p);
-}
-
-static void nsvg__parseRect(NSVGparser* p, const char** attr)
-{
- float x = 0.0f;
- float y = 0.0f;
- float w = 0.0f;
- float h = 0.0f;
- float rx = -1.0f; // marks not set
- float ry = -1.0f;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "width") == 0) w = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p));
- if (strcmp(attr[i], "height") == 0) h = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p));
- if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
- if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
- }
- }
-
- if (rx < 0.0f && ry > 0.0f) rx = ry;
- if (ry < 0.0f && rx > 0.0f) ry = rx;
- if (rx < 0.0f) rx = 0.0f;
- if (ry < 0.0f) ry = 0.0f;
- if (rx > w/2.0f) rx = w/2.0f;
- if (ry > h/2.0f) ry = h/2.0f;
-
- if (w != 0.0f && h != 0.0f) {
- nsvg__resetPath(p);
-
- if (rx < 0.00001f || ry < 0.0001f) {
- nsvg__moveTo(p, x, y);
- nsvg__lineTo(p, x+w, y);
- nsvg__lineTo(p, x+w, y+h);
- nsvg__lineTo(p, x, y+h);
- } else {
- // Rounded rectangle
- nsvg__moveTo(p, x+rx, y);
- nsvg__lineTo(p, x+w-rx, y);
- nsvg__cubicBezTo(p, x+w-rx*(1-NSVG_KAPPA90), y, x+w, y+ry*(1-NSVG_KAPPA90), x+w, y+ry);
- nsvg__lineTo(p, x+w, y+h-ry);
- nsvg__cubicBezTo(p, x+w, y+h-ry*(1-NSVG_KAPPA90), x+w-rx*(1-NSVG_KAPPA90), y+h, x+w-rx, y+h);
- nsvg__lineTo(p, x+rx, y+h);
- nsvg__cubicBezTo(p, x+rx*(1-NSVG_KAPPA90), y+h, x, y+h-ry*(1-NSVG_KAPPA90), x, y+h-ry);
- nsvg__lineTo(p, x, y+ry);
- nsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y);
- }
-
- nsvg__addPath(p, 1);
-
- nsvg__addShape(p);
- }
-}
-
-static void nsvg__parseCircle(NSVGparser* p, const char** attr)
-{
- float cx = 0.0f;
- float cy = 0.0f;
- float r = 0.0f;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "r") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p)));
- }
- }
-
- if (r > 0.0f) {
- nsvg__resetPath(p);
-
- nsvg__moveTo(p, cx+r, cy);
- nsvg__cubicBezTo(p, cx+r, cy+r*NSVG_KAPPA90, cx+r*NSVG_KAPPA90, cy+r, cx, cy+r);
- nsvg__cubicBezTo(p, cx-r*NSVG_KAPPA90, cy+r, cx-r, cy+r*NSVG_KAPPA90, cx-r, cy);
- nsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r);
- nsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy);
-
- nsvg__addPath(p, 1);
-
- nsvg__addShape(p);
- }
-}
-
-static void nsvg__parseEllipse(NSVGparser* p, const char** attr)
-{
- float cx = 0.0f;
- float cy = 0.0f;
- float rx = 0.0f;
- float ry = 0.0f;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
- if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
- }
- }
-
- if (rx > 0.0f && ry > 0.0f) {
-
- nsvg__resetPath(p);
-
- nsvg__moveTo(p, cx+rx, cy);
- nsvg__cubicBezTo(p, cx+rx, cy+ry*NSVG_KAPPA90, cx+rx*NSVG_KAPPA90, cy+ry, cx, cy+ry);
- nsvg__cubicBezTo(p, cx-rx*NSVG_KAPPA90, cy+ry, cx-rx, cy+ry*NSVG_KAPPA90, cx-rx, cy);
- nsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry);
- nsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy);
-
- nsvg__addPath(p, 1);
-
- nsvg__addShape(p);
- }
-}
-
-static void nsvg__parseLine(NSVGparser* p, const char** attr)
-{
- float x1 = 0.0;
- float y1 = 0.0;
- float x2 = 0.0;
- float y2 = 0.0;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "x1") == 0) x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "y1") == 0) y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "x2") == 0) x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "y2") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- }
- }
-
- nsvg__resetPath(p);
-
- nsvg__moveTo(p, x1, y1);
- nsvg__lineTo(p, x2, y2);
-
- nsvg__addPath(p, 0);
-
- nsvg__addShape(p);
-}
-
-static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag)
-{
- int i;
- const char* s;
- float args[2];
- int nargs, npts = 0;
- char item[64];
-
- nsvg__resetPath(p);
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "points") == 0) {
- s = attr[i + 1];
- nargs = 0;
- while (*s) {
- s = nsvg__getNextPathItem(s, item);
- args[nargs++] = (float)nsvg__atof(item);
- if (nargs >= 2) {
- if (npts == 0)
- nsvg__moveTo(p, args[0], args[1]);
- else
- nsvg__lineTo(p, args[0], args[1]);
- nargs = 0;
- npts++;
- }
- }
- }
- }
- }
-
- nsvg__addPath(p, (char)closeFlag);
-
- nsvg__addShape(p);
-}
-
-static void nsvg__parseSVG(NSVGparser* p, const char** attr)
-{
- int i;
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "width") == 0) {
- p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
- } else if (strcmp(attr[i], "height") == 0) {
- p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
- } else if (strcmp(attr[i], "viewBox") == 0) {
- sscanf(attr[i + 1], "%f%*[%%, \t]%f%*[%%, \t]%f%*[%%, \t]%f", &p->viewMinx, &p->viewMiny, &p->viewWidth, &p->viewHeight);
- } else if (strcmp(attr[i], "preserveAspectRatio") == 0) {
- if (strstr(attr[i + 1], "none") != 0) {
- // No uniform scaling
- p->alignType = NSVG_ALIGN_NONE;
- } else {
- // Parse X align
- if (strstr(attr[i + 1], "xMin") != 0)
- p->alignX = NSVG_ALIGN_MIN;
- else if (strstr(attr[i + 1], "xMid") != 0)
- p->alignX = NSVG_ALIGN_MID;
- else if (strstr(attr[i + 1], "xMax") != 0)
- p->alignX = NSVG_ALIGN_MAX;
- // Parse X align
- if (strstr(attr[i + 1], "yMin") != 0)
- p->alignY = NSVG_ALIGN_MIN;
- else if (strstr(attr[i + 1], "yMid") != 0)
- p->alignY = NSVG_ALIGN_MID;
- else if (strstr(attr[i + 1], "yMax") != 0)
- p->alignY = NSVG_ALIGN_MAX;
- // Parse meet/slice
- p->alignType = NSVG_ALIGN_MEET;
- if (strstr(attr[i + 1], "slice") != 0)
- p->alignType = NSVG_ALIGN_SLICE;
- }
- }
- }
- }
-}
-
-static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type)
-{
- int i;
- NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData));
- if (grad == NULL) return;
- memset(grad, 0, sizeof(NSVGgradientData));
- grad->units = NSVG_OBJECT_SPACE;
- grad->type = type;
- if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) {
- grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
- grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
- grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT);
- grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
- } else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) {
- grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
- grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
- grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
- }
-
- nsvg__xformIdentity(grad->xform);
-
- for (i = 0; attr[i]; i += 2) {
- if (strcmp(attr[i], "id") == 0) {
- strncpy(grad->id, attr[i+1], 63);
- grad->id[63] = '\0';
- } else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "gradientUnits") == 0) {
- if (strcmp(attr[i+1], "objectBoundingBox") == 0)
- grad->units = NSVG_OBJECT_SPACE;
- else
- grad->units = NSVG_USER_SPACE;
- } else if (strcmp(attr[i], "gradientTransform") == 0) {
- nsvg__parseTransform(grad->xform, attr[i + 1]);
- } else if (strcmp(attr[i], "cx") == 0) {
- grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "cy") == 0) {
- grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "r") == 0) {
- grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "fx") == 0) {
- grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "fy") == 0) {
- grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "x1") == 0) {
- grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "y1") == 0) {
- grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "x2") == 0) {
- grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "y2") == 0) {
- grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "spreadMethod") == 0) {
- if (strcmp(attr[i+1], "pad") == 0)
- grad->spread = NSVG_SPREAD_PAD;
- else if (strcmp(attr[i+1], "reflect") == 0)
- grad->spread = NSVG_SPREAD_REFLECT;
- else if (strcmp(attr[i+1], "repeat") == 0)
- grad->spread = NSVG_SPREAD_REPEAT;
- } else if (strcmp(attr[i], "xlink:href") == 0) {
- const char *href = attr[i+1];
- strncpy(grad->ref, href+1, 62);
- grad->ref[62] = '\0';
- }
- }
- }
-
- grad->next = p->gradients;
- p->gradients = grad;
-}
-
-static void nsvg__parseGradientStop(NSVGparser* p, const char** attr)
-{
- NSVGattrib* curAttr = nsvg__getAttr(p);
- NSVGgradientData* grad;
- NSVGgradientStop* stop;
- int i, idx;
-
- curAttr->stopOffset = 0;
- curAttr->stopColor = 0;
- curAttr->stopOpacity = 1.0f;
-
- for (i = 0; attr[i]; i += 2) {
- nsvg__parseAttr(p, attr[i], attr[i + 1]);
- }
-
- // Add stop to the last gradient.
- grad = p->gradients;
- if (grad == NULL) return;
-
- grad->nstops++;
- grad->stops = (NSVGgradientStop*)realloc(grad->stops, sizeof(NSVGgradientStop)*grad->nstops);
- if (grad->stops == NULL) return;
-
- // Insert
- idx = grad->nstops-1;
- for (i = 0; i < grad->nstops-1; i++) {
- if (curAttr->stopOffset < grad->stops[i].offset) {
- idx = i;
- break;
- }
- }
- if (idx != grad->nstops-1) {
- for (i = grad->nstops-1; i > idx; i--)
- grad->stops[i] = grad->stops[i-1];
- }
-
- stop = &grad->stops[idx];
- stop->color = curAttr->stopColor;
- stop->color |= (unsigned int)(curAttr->stopOpacity*255) << 24;
- stop->offset = curAttr->stopOffset;
-}
-
-static void nsvg__startElement(void* ud, const char* el, const char** attr)
-{
- NSVGparser* p = (NSVGparser*)ud;
-
- if (p->defsFlag) {
- // Skip everything but gradients in defs
- if (strcmp(el, "linearGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
- } else if (strcmp(el, "radialGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
- } else if (strcmp(el, "stop") == 0) {
- nsvg__parseGradientStop(p, attr);
- }
- return;
- }
-
- if (strcmp(el, "g") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseAttribs(p, attr);
- } else if (strcmp(el, "path") == 0) {
- if (p->pathFlag) // Do not allow nested paths.
- return;
- nsvg__pushAttr(p);
- nsvg__parsePath(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "rect") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseRect(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "circle") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseCircle(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "ellipse") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseEllipse(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "line") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseLine(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "polyline") == 0) {
- nsvg__pushAttr(p);
- nsvg__parsePoly(p, attr, 0);
- nsvg__popAttr(p);
- } else if (strcmp(el, "polygon") == 0) {
- nsvg__pushAttr(p);
- nsvg__parsePoly(p, attr, 1);
- nsvg__popAttr(p);
- } else if (strcmp(el, "linearGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
- } else if (strcmp(el, "radialGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
- } else if (strcmp(el, "stop") == 0) {
- nsvg__parseGradientStop(p, attr);
- } else if (strcmp(el, "defs") == 0) {
- p->defsFlag = 1;
- } else if (strcmp(el, "svg") == 0) {
- nsvg__parseSVG(p, attr);
- }
-}
-
-static void nsvg__endElement(void* ud, const char* el)
-{
- NSVGparser* p = (NSVGparser*)ud;
-
- if (strcmp(el, "g") == 0) {
- nsvg__popAttr(p);
- } else if (strcmp(el, "path") == 0) {
- p->pathFlag = 0;
- } else if (strcmp(el, "defs") == 0) {
- p->defsFlag = 0;
- }
-}
-
-static void nsvg__content(void* ud, const char* s)
-{
- NSVG_NOTUSED(ud);
- NSVG_NOTUSED(s);
- // empty
-}
-
-static void nsvg__imageBounds(NSVGparser* p, float* bounds)
-{
- NSVGshape* shape;
- shape = p->image->shapes;
- if (shape == NULL) {
- bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
- return;
- }
- bounds[0] = shape->bounds[0];
- bounds[1] = shape->bounds[1];
- bounds[2] = shape->bounds[2];
- bounds[3] = shape->bounds[3];
- for (shape = shape->next; shape != NULL; shape = shape->next) {
- bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]);
- bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]);
- bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]);
- bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]);
- }
-}
-
-static float nsvg__viewAlign(float content, float container, int type)
-{
- if (type == NSVG_ALIGN_MIN)
- return 0;
- else if (type == NSVG_ALIGN_MAX)
- return container - content;
- // mid
- return (container - content) * 0.5f;
-}
-
-static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy)
-{
- float t[6];
- nsvg__xformSetTranslation(t, tx, ty);
- nsvg__xformMultiply (grad->xform, t);
-
- nsvg__xformSetScale(t, sx, sy);
- nsvg__xformMultiply (grad->xform, t);
-}
-
-static void nsvg__scaleToViewbox(NSVGparser* p, const char* units)
-{
- NSVGshape* shape;
- NSVGpath* path;
- float tx, ty, sx, sy, us, bounds[4], t[6], avgs;
- int i;
- float* pt;
-
- // Guess image size if not set completely.
- nsvg__imageBounds(p, bounds);
-
- if (p->viewWidth == 0) {
- if (p->image->width > 0) {
- p->viewWidth = p->image->width;
- } else {
- p->viewMinx = bounds[0];
- p->viewWidth = bounds[2] - bounds[0];
- }
- }
- if (p->viewHeight == 0) {
- if (p->image->height > 0) {
- p->viewHeight = p->image->height;
- } else {
- p->viewMiny = bounds[1];
- p->viewHeight = bounds[3] - bounds[1];
- }
- }
- if (p->image->width == 0)
- p->image->width = p->viewWidth;
- if (p->image->height == 0)
- p->image->height = p->viewHeight;
-
- tx = -p->viewMinx;
- ty = -p->viewMiny;
- sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0;
- sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0;
- // Unit scaling
- us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f);
-
- // Fix aspect ratio
- if (p->alignType == NSVG_ALIGN_MEET) {
- // fit whole image into viewbox
- sx = sy = nsvg__minf(sx, sy);
- tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;
- ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;
- } else if (p->alignType == NSVG_ALIGN_SLICE) {
- // fill whole viewbox with image
- sx = sy = nsvg__maxf(sx, sy);
- tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;
- ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;
- }
-
- // Transform
- sx *= us;
- sy *= us;
- avgs = (sx+sy) / 2.0f;
- for (shape = p->image->shapes; shape != NULL; shape = shape->next) {
- shape->bounds[0] = (shape->bounds[0] + tx) * sx;
- shape->bounds[1] = (shape->bounds[1] + ty) * sy;
- shape->bounds[2] = (shape->bounds[2] + tx) * sx;
- shape->bounds[3] = (shape->bounds[3] + ty) * sy;
- for (path = shape->paths; path != NULL; path = path->next) {
- path->bounds[0] = (path->bounds[0] + tx) * sx;
- path->bounds[1] = (path->bounds[1] + ty) * sy;
- path->bounds[2] = (path->bounds[2] + tx) * sx;
- path->bounds[3] = (path->bounds[3] + ty) * sy;
- for (i =0; i < path->npts; i++) {
- pt = &path->pts[i*2];
- pt[0] = (pt[0] + tx) * sx;
- pt[1] = (pt[1] + ty) * sy;
- }
- }
-
- if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) {
- nsvg__scaleGradient(shape->fill.gradient, tx,ty, sx,sy);
- memcpy(t, shape->fill.gradient->xform, sizeof(float)*6);
- nsvg__xformInverse(shape->fill.gradient->xform, t);
- }
- if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) {
- nsvg__scaleGradient(shape->stroke.gradient, tx,ty, sx,sy);
- memcpy(t, shape->stroke.gradient->xform, sizeof(float)*6);
- nsvg__xformInverse(shape->stroke.gradient->xform, t);
- }
-
- shape->strokeWidth *= avgs;
- shape->strokeDashOffset *= avgs;
- for (i = 0; i < shape->strokeDashCount; i++)
- shape->strokeDashArray[i] *= avgs;
- }
-}
-
-NSVGimage* nsvgParse(char* input, const char* units, float dpi)
-{
- NSVGparser* p;
- NSVGimage* ret = 0;
-
- p = nsvg__createParser();
- if (p == NULL) {
- return NULL;
- }
- p->dpi = dpi;
-
- nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
-
- // Scale to viewBox
- nsvg__scaleToViewbox(p, units);
-
- ret = p->image;
- p->image = NULL;
-
- nsvg__deleteParser(p);
-
- return ret;
-}
-
-NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
-{
- FILE* fp = NULL;
- size_t size;
- char* data = NULL;
- NSVGimage* image = NULL;
-
- fp = fopen(filename, "rb");
- if (!fp) goto error;
- fseek(fp, 0, SEEK_END);
- size = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- data = (char*)malloc(size+1);
- if (data == NULL) goto error;
- if (fread(data, 1, size, fp) != size) goto error;
- data[size] = '\0'; // Must be null terminated.
- fclose(fp);
- image = nsvgParse(data, units, dpi);
- free(data);
-
- return image;
+static unsigned int nsvg__parseColorName(const char *str) {
+ int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);
+
+ for (i = 0; i < ncolors; i++) {
+ if (strcmp(nsvg__colors[i].name, str) == 0) {
+ return nsvg__colors[i].color;
+ }
+ }
+
+ return NSVG_RGB(128, 128, 128);
+}
+
+static unsigned int nsvg__parseColor(const char *str) {
+ size_t len = 0;
+ while (*str == ' ')
+ ++str;
+ len = strlen(str);
+ if (len >= 1 && *str == '#')
+ return nsvg__parseColorHex(str);
+ else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(')
+ return nsvg__parseColorRGB(str);
+ return nsvg__parseColorName(str);
+}
+
+static float nsvg__parseOpacity(const char *str) {
+ float val = 0;
+ sscanf(str, "%f", &val);
+ if (val < 0.0f)
+ val = 0.0f;
+ if (val > 1.0f)
+ val = 1.0f;
+ return val;
+}
+
+static float nsvg__parseMiterLimit(const char *str) {
+ float val = 0;
+ sscanf(str, "%f", &val);
+ if (val < 0.0f)
+ val = 0.0f;
+ return val;
+}
+
+static int nsvg__parseUnits(const char *units) {
+ if (units[0] == 'p' && units[1] == 'x')
+ return NSVG_UNITS_PX;
+ else if (units[0] == 'p' && units[1] == 't')
+ return NSVG_UNITS_PT;
+ else if (units[0] == 'p' && units[1] == 'c')
+ return NSVG_UNITS_PC;
+ else if (units[0] == 'm' && units[1] == 'm')
+ return NSVG_UNITS_MM;
+ else if (units[0] == 'c' && units[1] == 'm')
+ return NSVG_UNITS_CM;
+ else if (units[0] == 'i' && units[1] == 'n')
+ return NSVG_UNITS_IN;
+ else if (units[0] == '%')
+ return NSVG_UNITS_PERCENT;
+ else if (units[0] == 'e' && units[1] == 'm')
+ return NSVG_UNITS_EM;
+ else if (units[0] == 'e' && units[1] == 'x')
+ return NSVG_UNITS_EX;
+ return NSVG_UNITS_USER;
+}
+
+static NSVGcoordinate nsvg__parseCoordinateRaw(const char *str) {
+ NSVGcoordinate coord = {0, NSVG_UNITS_USER};
+ char units[32] = "";
+ sscanf(str, "%f%31s", &coord.value, units);
+ coord.units = nsvg__parseUnits(units);
+ return coord;
+}
+
+static NSVGcoordinate nsvg__coord(float v, int units) {
+ NSVGcoordinate coord = {v, units};
+ return coord;
+}
+
+static float nsvg__parseCoordinate(NSVGparser *p, const char *str, float orig, float length) {
+ NSVGcoordinate coord = nsvg__parseCoordinateRaw(str);
+ return nsvg__convertToPixels(p, coord, orig, length);
+}
+
+static int nsvg__parseTransformArgs(const char *str, float *args, int maxNa, int *na) {
+ const char *end;
+ const char *ptr;
+ char it[64];
+
+ *na = 0;
+ ptr = str;
+ while (*ptr && *ptr != '(')
+ ++ptr;
+ if (*ptr == 0)
+ return 1;
+ end = ptr;
+ while (*end && *end != ')')
+ ++end;
+ if (*end == 0)
+ return 1;
+
+ while (ptr < end) {
+ if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) {
+ if (*na >= maxNa)
+ return 0;
+ ptr = nsvg__parseNumber(ptr, it, 64);
+ args[(*na)++] = (float)nsvg__atof(it);
+ } else {
+ ++ptr;
+ }
+ }
+ return (int)(end - str);
+}
+
+static int nsvg__parseMatrix(float *xform, const char *str) {
+ float t[6];
+ int na = 0;
+ int len = nsvg__parseTransformArgs(str, t, 6, &na);
+ if (na != 6)
+ return len;
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseTranslate(float *xform, const char *str) {
+ float args[2];
+ float t[6];
+ int na = 0;
+ int len = nsvg__parseTransformArgs(str, args, 2, &na);
+ if (na == 1)
+ args[1] = 0.0;
+
+ nsvg__xformSetTranslation(t, args[0], args[1]);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseScale(float *xform, const char *str) {
+ float args[2];
+ int na = 0;
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 2, &na);
+ if (na == 1)
+ args[1] = args[0];
+ nsvg__xformSetScale(t, args[0], args[1]);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseSkewX(float *xform, const char *str) {
+ float args[1];
+ int na = 0;
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 1, &na);
+ nsvg__xformSetSkewX(t, args[0] / 180.0f * NSVG_PI);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseSkewY(float *xform, const char *str) {
+ float args[1];
+ int na = 0;
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 1, &na);
+ nsvg__xformSetSkewY(t, args[0] / 180.0f * NSVG_PI);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseRotate(float *xform, const char *str) {
+ float args[3];
+ int na = 0;
+ float m[6];
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 3, &na);
+ if (na == 1)
+ args[1] = args[2] = 0.0f;
+ nsvg__xformIdentity(m);
+
+ if (na > 1) {
+ nsvg__xformSetTranslation(t, -args[1], -args[2]);
+ nsvg__xformMultiply(m, t);
+ }
+
+ nsvg__xformSetRotation(t, args[0] / 180.0f * NSVG_PI);
+ nsvg__xformMultiply(m, t);
+
+ if (na > 1) {
+ nsvg__xformSetTranslation(t, args[1], args[2]);
+ nsvg__xformMultiply(m, t);
+ }
+
+ memcpy(xform, m, sizeof(float) * 6);
+
+ return len;
+}
+
+static void nsvg__parseTransform(float *xform, const char *str) {
+ float t[6];
+ nsvg__xformIdentity(xform);
+ while (*str) {
+ if (strncmp(str, "matrix", 6) == 0)
+ str += nsvg__parseMatrix(t, str);
+ else if (strncmp(str, "translate", 9) == 0)
+ str += nsvg__parseTranslate(t, str);
+ else if (strncmp(str, "scale", 5) == 0)
+ str += nsvg__parseScale(t, str);
+ else if (strncmp(str, "rotate", 6) == 0)
+ str += nsvg__parseRotate(t, str);
+ else if (strncmp(str, "skewX", 5) == 0)
+ str += nsvg__parseSkewX(t, str);
+ else if (strncmp(str, "skewY", 5) == 0)
+ str += nsvg__parseSkewY(t, str);
+ else {
+ ++str;
+ continue;
+ }
+
+ nsvg__xformPremultiply(xform, t);
+ }
+}
+
+static void nsvg__parseUrl(char *id, const char *str) {
+ int i = 0;
+ str += 4; // "url(";
+ if (*str == '#')
+ str++;
+ while (i < 63 && *str != ')') {
+ id[i] = *str++;
+ i++;
+ }
+ id[i] = '\0';
+}
+
+static char nsvg__parseLineCap(const char *str) {
+ if (strcmp(str, "butt") == 0)
+ return NSVG_CAP_BUTT;
+ else if (strcmp(str, "round") == 0)
+ return NSVG_CAP_ROUND;
+ else if (strcmp(str, "square") == 0)
+ return NSVG_CAP_SQUARE;
+ // TODO: handle inherit.
+ return NSVG_CAP_BUTT;
+}
+
+static char nsvg__parseLineJoin(const char *str) {
+ if (strcmp(str, "miter") == 0)
+ return NSVG_JOIN_MITER;
+ else if (strcmp(str, "round") == 0)
+ return NSVG_JOIN_ROUND;
+ else if (strcmp(str, "bevel") == 0)
+ return NSVG_JOIN_BEVEL;
+ // TODO: handle inherit.
+ return NSVG_JOIN_MITER;
+}
+
+static char nsvg__parseFillRule(const char *str) {
+ if (strcmp(str, "nonzero") == 0)
+ return NSVG_FILLRULE_NONZERO;
+ else if (strcmp(str, "evenodd") == 0)
+ return NSVG_FILLRULE_EVENODD;
+ // TODO: handle inherit.
+ return NSVG_FILLRULE_NONZERO;
+}
+
+static const char *nsvg__getNextDashItem(const char *s, char *it) {
+ int n = 0;
+ it[0] = '\0';
+ // Skip white spaces and commas
+ while (*s && (nsvg__isspace(*s) || *s == ','))
+ s++;
+ // Advance until whitespace, comma or end.
+ while (*s && (!nsvg__isspace(*s) && *s != ',')) {
+ if (n < 63)
+ it[n++] = *s;
+ s++;
+ }
+ it[n++] = '\0';
+ return s;
+}
+
+static int nsvg__parseStrokeDashArray(NSVGparser *p, const char *str, float *strokeDashArray) {
+ char item[64];
+ int count = 0, i;
+ float sum = 0.0f;
+
+ // Handle "none"
+ if (str[0] == 'n')
+ return 0;
+
+ // Parse dashes
+ while (*str) {
+ str = nsvg__getNextDashItem(str, item);
+ if (!*item)
+ break;
+ if (count < NSVG_MAX_DASHES)
+ strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p)));
+ }
+
+ for (i = 0; i < count; i++)
+ sum += strokeDashArray[i];
+ if (sum <= 1e-6f)
+ count = 0;
+
+ return count;
+}
+
+static void nsvg__parseStyle(NSVGparser *p, const char *str);
+
+static int nsvg__parseAttr(NSVGparser *p, const char *name, const char *value) {
+ float xform[6];
+ NSVGattrib *attr = nsvg__getAttr(p);
+ if (!attr)
+ return 0;
+
+ if (strcmp(name, "style") == 0) {
+ nsvg__parseStyle(p, value);
+ } else if (strcmp(name, "display") == 0) {
+ if (strcmp(value, "none") == 0)
+ attr->visible = 0;
+ // Don't reset ->visible on display:inline, one display:none hides the whole subtree
+
+ } else if (strcmp(name, "fill") == 0) {
+ if (strcmp(value, "none") == 0) {
+ attr->hasFill = 0;
+ } else if (strncmp(value, "url(", 4) == 0) {
+ attr->hasFill = 2;
+ nsvg__parseUrl(attr->fillGradient, value);
+ } else {
+ attr->hasFill = 1;
+ attr->fillColor = nsvg__parseColor(value);
+ }
+ } else if (strcmp(name, "opacity") == 0) {
+ attr->opacity = nsvg__parseOpacity(value);
+ } else if (strcmp(name, "fill-opacity") == 0) {
+ attr->fillOpacity = nsvg__parseOpacity(value);
+ } else if (strcmp(name, "stroke") == 0) {
+ if (strcmp(value, "none") == 0) {
+ attr->hasStroke = 0;
+ } else if (strncmp(value, "url(", 4) == 0) {
+ attr->hasStroke = 2;
+ nsvg__parseUrl(attr->strokeGradient, value);
+ } else {
+ attr->hasStroke = 1;
+ attr->strokeColor = nsvg__parseColor(value);
+ }
+ } else if (strcmp(name, "stroke-width") == 0) {
+ attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
+ } else if (strcmp(name, "stroke-dasharray") == 0) {
+ attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray);
+ } else if (strcmp(name, "stroke-dashoffset") == 0) {
+ attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
+ } else if (strcmp(name, "stroke-opacity") == 0) {
+ attr->strokeOpacity = nsvg__parseOpacity(value);
+ } else if (strcmp(name, "stroke-linecap") == 0) {
+ attr->strokeLineCap = nsvg__parseLineCap(value);
+ } else if (strcmp(name, "stroke-linejoin") == 0) {
+ attr->strokeLineJoin = nsvg__parseLineJoin(value);
+ } else if (strcmp(name, "stroke-miterlimit") == 0) {
+ attr->miterLimit = nsvg__parseMiterLimit(value);
+ } else if (strcmp(name, "fill-rule") == 0) {
+ attr->fillRule = nsvg__parseFillRule(value);
+ } else if (strcmp(name, "font-size") == 0) {
+ attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
+ } else if (strcmp(name, "transform") == 0) {
+ nsvg__parseTransform(xform, value);
+ nsvg__xformPremultiply(attr->xform, xform);
+ } else if (strcmp(name, "stop-color") == 0) {
+ attr->stopColor = nsvg__parseColor(value);
+ } else if (strcmp(name, "stop-opacity") == 0) {
+ attr->stopOpacity = nsvg__parseOpacity(value);
+ } else if (strcmp(name, "offset") == 0) {
+ attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);
+ } else if (strcmp(name, "id") == 0) {
+ strncpy(attr->id, value, 63);
+ attr->id[63] = '\0';
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static int nsvg__parseNameValue(NSVGparser *p, const char *start, const char *end) {
+ const char *str;
+ const char *val;
+ char name[512];
+ char value[512];
+ int n;
+
+ str = start;
+ while (str < end && *str != ':')
+ ++str;
+
+ val = str;
+
+ // Right Trim
+ while (str > start && (*str == ':' || nsvg__isspace(*str)))
+ --str;
+ ++str;
+
+ n = (int)(str - start);
+ if (n > 511)
+ n = 511;
+ if (n)
+ memcpy(name, start, n);
+ name[n] = 0;
+
+ while (val < end && (*val == ':' || nsvg__isspace(*val)))
+ ++val;
+
+ n = (int)(end - val);
+ if (n > 511)
+ n = 511;
+ if (n)
+ memcpy(value, val, n);
+ value[n] = 0;
+
+ return nsvg__parseAttr(p, name, value);
+}
+
+static void nsvg__parseStyle(NSVGparser *p, const char *str) {
+ const char *start;
+ const char *end;
+
+ while (*str) {
+ // Left Trim
+ while (*str && nsvg__isspace(*str))
+ ++str;
+ start = str;
+ while (*str && *str != ';')
+ ++str;
+ end = str;
+
+ // Right Trim
+ while (end > start && (*end == ';' || nsvg__isspace(*end)))
+ --end;
+ ++end;
+
+ nsvg__parseNameValue(p, start, end);
+ if (*str)
+ ++str;
+ }
+}
+
+static void nsvg__parseAttribs(NSVGparser *p, const char **attr) {
+ int i;
+ for (i = 0; attr[i]; i += 2) {
+ if (strcmp(attr[i], "style") == 0)
+ nsvg__parseStyle(p, attr[i + 1]);
+ else
+ nsvg__parseAttr(p, attr[i], attr[i + 1]);
+ }
+}
+
+static int nsvg__getArgsPerElement(char cmd) {
+ switch (cmd) {
+ case 'v':
+ case 'V':
+ case 'h':
+ case 'H':
+ return 1;
+ case 'm':
+ case 'M':
+ case 'l':
+ case 'L':
+ case 't':
+ case 'T':
+ return 2;
+ case 'q':
+ case 'Q':
+ case 's':
+ case 'S':
+ return 4;
+ case 'c':
+ case 'C':
+ return 6;
+ case 'a':
+ case 'A':
+ return 7;
+ }
+ return 0;
+}
+
+static void nsvg__pathMoveTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+ if (rel) {
+ *cpx += args[0];
+ *cpy += args[1];
+ } else {
+ *cpx = args[0];
+ *cpy = args[1];
+ }
+ nsvg__moveTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathLineTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+ if (rel) {
+ *cpx += args[0];
+ *cpy += args[1];
+ } else {
+ *cpx = args[0];
+ *cpy = args[1];
+ }
+ nsvg__lineTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathHLineTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+ if (rel)
+ *cpx += args[0];
+ else
+ *cpx = args[0];
+ nsvg__lineTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathVLineTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+ if (rel)
+ *cpy += args[0];
+ else
+ *cpy = args[0];
+ nsvg__lineTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathCubicBezTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+ int rel) {
+ float x2, y2, cx1, cy1, cx2, cy2;
+
+ if (rel) {
+ cx1 = *cpx + args[0];
+ cy1 = *cpy + args[1];
+ cx2 = *cpx + args[2];
+ cy2 = *cpy + args[3];
+ x2 = *cpx + args[4];
+ y2 = *cpy + args[5];
+ } else {
+ cx1 = args[0];
+ cy1 = args[1];
+ cx2 = args[2];
+ cy2 = args[3];
+ x2 = args[4];
+ y2 = args[5];
+ }
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx2;
+ *cpy2 = cy2;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__pathCubicBezShortTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+ int rel) {
+ float x1, y1, x2, y2, cx1, cy1, cx2, cy2;
+
+ x1 = *cpx;
+ y1 = *cpy;
+ if (rel) {
+ cx2 = *cpx + args[0];
+ cy2 = *cpy + args[1];
+ x2 = *cpx + args[2];
+ y2 = *cpy + args[3];
+ } else {
+ cx2 = args[0];
+ cy2 = args[1];
+ x2 = args[2];
+ y2 = args[3];
+ }
+
+ cx1 = 2 * x1 - *cpx2;
+ cy1 = 2 * y1 - *cpy2;
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx2;
+ *cpy2 = cy2;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__pathQuadBezTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args, int rel) {
+ float x1, y1, x2, y2, cx, cy;
+ float cx1, cy1, cx2, cy2;
+
+ x1 = *cpx;
+ y1 = *cpy;
+ if (rel) {
+ cx = *cpx + args[0];
+ cy = *cpy + args[1];
+ x2 = *cpx + args[2];
+ y2 = *cpy + args[3];
+ } else {
+ cx = args[0];
+ cy = args[1];
+ x2 = args[2];
+ y2 = args[3];
+ }
+
+ // Convert to cubic bezier
+ cx1 = x1 + 2.0f / 3.0f * (cx - x1);
+ cy1 = y1 + 2.0f / 3.0f * (cy - y1);
+ cx2 = x2 + 2.0f / 3.0f * (cx - x2);
+ cy2 = y2 + 2.0f / 3.0f * (cy - y2);
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx;
+ *cpy2 = cy;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__pathQuadBezShortTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+ int rel) {
+ float x1, y1, x2, y2, cx, cy;
+ float cx1, cy1, cx2, cy2;
+
+ x1 = *cpx;
+ y1 = *cpy;
+ if (rel) {
+ x2 = *cpx + args[0];
+ y2 = *cpy + args[1];
+ } else {
+ x2 = args[0];
+ y2 = args[1];
+ }
+
+ cx = 2 * x1 - *cpx2;
+ cy = 2 * y1 - *cpy2;
+
+ // Convert to cubix bezier
+ cx1 = x1 + 2.0f / 3.0f * (cx - x1);
+ cy1 = y1 + 2.0f / 3.0f * (cy - y1);
+ cx2 = x2 + 2.0f / 3.0f * (cx - x2);
+ cy2 = y2 + 2.0f / 3.0f * (cy - y2);
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx;
+ *cpy2 = cy;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static float nsvg__sqr(float x) { return x * x; }
+static float nsvg__vmag(float x, float y) { return sqrtf(x * x + y * y); }
+
+static float nsvg__vecrat(float ux, float uy, float vx, float vy) {
+ return (ux * vx + uy * vy) / (nsvg__vmag(ux, uy) * nsvg__vmag(vx, vy));
+}
+
+static float nsvg__vecang(float ux, float uy, float vx, float vy) {
+ float r = nsvg__vecrat(ux, uy, vx, vy);
+ if (r < -1.0f)
+ r = -1.0f;
+ if (r > 1.0f)
+ r = 1.0f;
+ return ((ux * vy < uy * vx) ? -1.0f : 1.0f) * acosf(r);
+}
+
+static void nsvg__pathArcTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+ // Ported from canvg (https://code.google.com/p/canvg/)
+ float rx, ry, rotx;
+ float x1, y1, x2, y2, cx, cy, dx, dy, d;
+ float x1p, y1p, cxp, cyp, s, sa, sb;
+ float ux, uy, vx, vy, a1, da;
+ float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6];
+ float sinrx, cosrx;
+ int fa, fs;
+ int i, ndivs;
+ float hda, kappa;
+
+ rx = fabsf(args[0]); // y radius
+ ry = fabsf(args[1]); // x radius
+ rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle
+ fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc
+ fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction
+ x1 = *cpx; // start point
+ y1 = *cpy;
+ if (rel) { // end point
+ x2 = *cpx + args[5];
+ y2 = *cpy + args[6];
+ } else {
+ x2 = args[5];
+ y2 = args[6];
+ }
+
+ dx = x1 - x2;
+ dy = y1 - y2;
+ d = sqrtf(dx * dx + dy * dy);
+ if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) {
+ // The arc degenerates to a line
+ nsvg__lineTo(p, x2, y2);
+ *cpx = x2;
+ *cpy = y2;
+ return;
+ }
+
+ sinrx = sinf(rotx);
+ cosrx = cosf(rotx);
+
+ // Convert to center point parameterization.
+ // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
+ // 1) Compute x1', y1'
+ x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f;
+ y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f;
+ d = nsvg__sqr(x1p) / nsvg__sqr(rx) + nsvg__sqr(y1p) / nsvg__sqr(ry);
+ if (d > 1) {
+ d = sqrtf(d);
+ rx *= d;
+ ry *= d;
+ }
+ // 2) Compute cx', cy'
+ s = 0.0f;
+ sa = nsvg__sqr(rx) * nsvg__sqr(ry) - nsvg__sqr(rx) * nsvg__sqr(y1p) - nsvg__sqr(ry) * nsvg__sqr(x1p);
+ sb = nsvg__sqr(rx) * nsvg__sqr(y1p) + nsvg__sqr(ry) * nsvg__sqr(x1p);
+ if (sa < 0.0f)
+ sa = 0.0f;
+ if (sb > 0.0f)
+ s = sqrtf(sa / sb);
+ if (fa == fs)
+ s = -s;
+ cxp = s * rx * y1p / ry;
+ cyp = s * -ry * x1p / rx;
+
+ // 3) Compute cx,cy from cx',cy'
+ cx = (x1 + x2) / 2.0f + cosrx * cxp - sinrx * cyp;
+ cy = (y1 + y2) / 2.0f + sinrx * cxp + cosrx * cyp;
+
+ // 4) Calculate theta1, and delta theta.
+ ux = (x1p - cxp) / rx;
+ uy = (y1p - cyp) / ry;
+ vx = (-x1p - cxp) / rx;
+ vy = (-y1p - cyp) / ry;
+ a1 = nsvg__vecang(1.0f, 0.0f, ux, uy); // Initial angle
+ da = nsvg__vecang(ux, uy, vx, vy); // Delta angle
+
+ // if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI;
+ // if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0;
+
+ if (fs == 0 && da > 0)
+ da -= 2 * NSVG_PI;
+ else if (fs == 1 && da < 0)
+ da += 2 * NSVG_PI;
+
+ // Approximate the arc using cubic spline segments.
+ t[0] = cosrx;
+ t[1] = sinrx;
+ t[2] = -sinrx;
+ t[3] = cosrx;
+ t[4] = cx;
+ t[5] = cy;
+
+ // Split arc into max 90 degree segments.
+ // The loop assumes an iteration per end point (including start and end), this +1.
+ ndivs = (int)(fabsf(da) / (NSVG_PI * 0.5f) + 1.0f);
+ hda = (da / (float)ndivs) / 2.0f;
+ kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda));
+ if (da < 0.0f)
+ kappa = -kappa;
+
+ for (i = 0; i <= ndivs; i++) {
+ a = a1 + da * ((float)i / (float)ndivs);
+ dx = cosf(a);
+ dy = sinf(a);
+ nsvg__xformPoint(&x, &y, dx * rx, dy * ry, t); // position
+ nsvg__xformVec(&tanx, &tany, -dy * rx * kappa, dx * ry * kappa, t); // tangent
+ if (i > 0)
+ nsvg__cubicBezTo(p, px + ptanx, py + ptany, x - tanx, y - tany, x, y);
+ px = x;
+ py = y;
+ ptanx = tanx;
+ ptany = tany;
+ }
+
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__parsePath(NSVGparser *p, const char **attr) {
+ const char *s = NULL;
+ char cmd = '\0';
+ float args[10];
+ int nargs;
+ int rargs = 0;
+ float cpx, cpy, cpx2, cpy2;
+ const char *tmp[4];
+ char closedFlag;
+ int i;
+ char item[64];
+
+ for (i = 0; attr[i]; i += 2) {
+ if (strcmp(attr[i], "d") == 0) {
+ s = attr[i + 1];
+ } else {
+ tmp[0] = attr[i];
+ tmp[1] = attr[i + 1];
+ tmp[2] = 0;
+ tmp[3] = 0;
+ nsvg__parseAttribs(p, tmp);
+ }
+ }
+
+ if (s) {
+ nsvg__resetPath(p);
+ cpx = 0;
+ cpy = 0;
+ cpx2 = 0;
+ cpy2 = 0;
+ closedFlag = 0;
+ nargs = 0;
+
+ while (*s) {
+ s = nsvg__getNextPathItem(s, item);
+ if (!*item)
+ break;
+ if (nsvg__isnum(item[0])) {
+ if (nargs < 10)
+ args[nargs++] = (float)nsvg__atof(item);
+ if (nargs >= rargs) {
+ switch (cmd) {
+ case 'm':
+ case 'M':
+ nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);
+ // Moveto can be followed by multiple coordinate pairs,
+ // which should be treated as linetos.
+ cmd = (cmd == 'm') ? 'l' : 'L';
+ rargs = nsvg__getArgsPerElement(cmd);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ case 'l':
+ case 'L':
+ nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ case 'H':
+ case 'h':
+ nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ case 'V':
+ case 'v':
+ nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ case 'C':
+ case 'c':
+ nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
+ break;
+ case 'S':
+ case 's':
+ nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
+ break;
+ case 'Q':
+ case 'q':
+ nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
+ break;
+ case 'T':
+ case 't':
+ nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0);
+ break;
+ case 'A':
+ case 'a':
+ nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ default:
+ if (nargs >= 2) {
+ cpx = args[nargs - 2];
+ cpy = args[nargs - 1];
+ cpx2 = cpx;
+ cpy2 = cpy;
+ }
+ break;
+ }
+ nargs = 0;
+ }
+ } else {
+ cmd = item[0];
+ rargs = nsvg__getArgsPerElement(cmd);
+ if (cmd == 'M' || cmd == 'm') {
+ // Commit path.
+ if (p->npts > 0)
+ nsvg__addPath(p, closedFlag);
+ // Start new subpath.
+ nsvg__resetPath(p);
+ closedFlag = 0;
+ nargs = 0;
+ } else if (cmd == 'Z' || cmd == 'z') {
+ closedFlag = 1;
+ // Commit path.
+ if (p->npts > 0) {
+ // Move current point to first point
+ cpx = p->pts[0];
+ cpy = p->pts[1];
+ cpx2 = cpx;
+ cpy2 = cpy;
+ nsvg__addPath(p, closedFlag);
+ }
+ // Start new subpath.
+ nsvg__resetPath(p);
+ nsvg__moveTo(p, cpx, cpy);
+ closedFlag = 0;
+ nargs = 0;
+ }
+ }
+ }
+ // Commit path.
+ if (p->npts)
+ nsvg__addPath(p, closedFlag);
+ }
+
+ nsvg__addShape(p);
+}
+
+static void nsvg__parseRect(NSVGparser *p, const char **attr) {
+ float x = 0.0f;
+ float y = 0.0f;
+ float w = 0.0f;
+ float h = 0.0f;
+ float rx = -1.0f; // marks not set
+ float ry = -1.0f;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "x") == 0)
+ x = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "y") == 0)
+ y = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "width") == 0)
+ w = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p));
+ if (strcmp(attr[i], "height") == 0)
+ h = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p));
+ if (strcmp(attr[i], "rx") == 0)
+ rx = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p)));
+ if (strcmp(attr[i], "ry") == 0)
+ ry = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p)));
+ }
+ }
+
+ if (rx < 0.0f && ry > 0.0f)
+ rx = ry;
+ if (ry < 0.0f && rx > 0.0f)
+ ry = rx;
+ if (rx < 0.0f)
+ rx = 0.0f;
+ if (ry < 0.0f)
+ ry = 0.0f;
+ if (rx > w / 2.0f)
+ rx = w / 2.0f;
+ if (ry > h / 2.0f)
+ ry = h / 2.0f;
+
+ if (w != 0.0f && h != 0.0f) {
+ nsvg__resetPath(p);
+
+ if (rx < 0.00001f || ry < 0.0001f) {
+ nsvg__moveTo(p, x, y);
+ nsvg__lineTo(p, x + w, y);
+ nsvg__lineTo(p, x + w, y + h);
+ nsvg__lineTo(p, x, y + h);
+ } else {
+ // Rounded rectangle
+ nsvg__moveTo(p, x + rx, y);
+ nsvg__lineTo(p, x + w - rx, y);
+ nsvg__cubicBezTo(p, x + w - rx * (1 - NSVG_KAPPA90), y, x + w, y + ry * (1 - NSVG_KAPPA90), x + w, y + ry);
+ nsvg__lineTo(p, x + w, y + h - ry);
+ nsvg__cubicBezTo(p, x + w, y + h - ry * (1 - NSVG_KAPPA90), x + w - rx * (1 - NSVG_KAPPA90), y + h,
+ x + w - rx, y + h);
+ nsvg__lineTo(p, x + rx, y + h);
+ nsvg__cubicBezTo(p, x + rx * (1 - NSVG_KAPPA90), y + h, x, y + h - ry * (1 - NSVG_KAPPA90), x, y + h - ry);
+ nsvg__lineTo(p, x, y + ry);
+ nsvg__cubicBezTo(p, x, y + ry * (1 - NSVG_KAPPA90), x + rx * (1 - NSVG_KAPPA90), y, x + rx, y);
+ }
+
+ nsvg__addPath(p, 1);
+
+ nsvg__addShape(p);
+ }
+}
+
+static void nsvg__parseCircle(NSVGparser *p, const char **attr) {
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float r = 0.0f;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "cx") == 0)
+ cx = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "cy") == 0)
+ cy = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "r") == 0)
+ r = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualLength(p)));
+ }
+ }
+
+ if (r > 0.0f) {
+ nsvg__resetPath(p);
+
+ nsvg__moveTo(p, cx + r, cy);
+ nsvg__cubicBezTo(p, cx + r, cy + r * NSVG_KAPPA90, cx + r * NSVG_KAPPA90, cy + r, cx, cy + r);
+ nsvg__cubicBezTo(p, cx - r * NSVG_KAPPA90, cy + r, cx - r, cy + r * NSVG_KAPPA90, cx - r, cy);
+ nsvg__cubicBezTo(p, cx - r, cy - r * NSVG_KAPPA90, cx - r * NSVG_KAPPA90, cy - r, cx, cy - r);
+ nsvg__cubicBezTo(p, cx + r * NSVG_KAPPA90, cy - r, cx + r, cy - r * NSVG_KAPPA90, cx + r, cy);
+
+ nsvg__addPath(p, 1);
+
+ nsvg__addShape(p);
+ }
+}
+
+static void nsvg__parseEllipse(NSVGparser *p, const char **attr) {
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float rx = 0.0f;
+ float ry = 0.0f;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "cx") == 0)
+ cx = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "cy") == 0)
+ cy = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "rx") == 0)
+ rx = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p)));
+ if (strcmp(attr[i], "ry") == 0)
+ ry = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p)));
+ }
+ }
+
+ if (rx > 0.0f && ry > 0.0f) {
+
+ nsvg__resetPath(p);
+
+ nsvg__moveTo(p, cx + rx, cy);
+ nsvg__cubicBezTo(p, cx + rx, cy + ry * NSVG_KAPPA90, cx + rx * NSVG_KAPPA90, cy + ry, cx, cy + ry);
+ nsvg__cubicBezTo(p, cx - rx * NSVG_KAPPA90, cy + ry, cx - rx, cy + ry * NSVG_KAPPA90, cx - rx, cy);
+ nsvg__cubicBezTo(p, cx - rx, cy - ry * NSVG_KAPPA90, cx - rx * NSVG_KAPPA90, cy - ry, cx, cy - ry);
+ nsvg__cubicBezTo(p, cx + rx * NSVG_KAPPA90, cy - ry, cx + rx, cy - ry * NSVG_KAPPA90, cx + rx, cy);
+
+ nsvg__addPath(p, 1);
+
+ nsvg__addShape(p);
+ }
+}
+
+static void nsvg__parseLine(NSVGparser *p, const char **attr) {
+ float x1 = 0.0;
+ float y1 = 0.0;
+ float x2 = 0.0;
+ float y2 = 0.0;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "x1") == 0)
+ x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "y1") == 0)
+ y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "x2") == 0)
+ x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "y2") == 0)
+ y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ }
+ }
+
+ nsvg__resetPath(p);
+
+ nsvg__moveTo(p, x1, y1);
+ nsvg__lineTo(p, x2, y2);
+
+ nsvg__addPath(p, 0);
+
+ nsvg__addShape(p);
+}
+
+static void nsvg__parsePoly(NSVGparser *p, const char **attr, int closeFlag) {
+ int i;
+ const char *s;
+ float args[2];
+ int nargs, npts = 0;
+ char item[64];
+
+ nsvg__resetPath(p);
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "points") == 0) {
+ s = attr[i + 1];
+ nargs = 0;
+ while (*s) {
+ s = nsvg__getNextPathItem(s, item);
+ args[nargs++] = (float)nsvg__atof(item);
+ if (nargs >= 2) {
+ if (npts == 0)
+ nsvg__moveTo(p, args[0], args[1]);
+ else
+ nsvg__lineTo(p, args[0], args[1]);
+ nargs = 0;
+ npts++;
+ }
+ }
+ }
+ }
+ }
+
+ nsvg__addPath(p, (char)closeFlag);
+
+ nsvg__addShape(p);
+}
+
+static void nsvg__parseSVG(NSVGparser *p, const char **attr) {
+ int i;
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "width") == 0) {
+ p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
+ } else if (strcmp(attr[i], "height") == 0) {
+ p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
+ } else if (strcmp(attr[i], "viewBox") == 0) {
+ sscanf(attr[i + 1], "%f%*[%%, \t]%f%*[%%, \t]%f%*[%%, \t]%f", &p->viewMinx, &p->viewMiny, &p->viewWidth,
+ &p->viewHeight);
+ } else if (strcmp(attr[i], "preserveAspectRatio") == 0) {
+ if (strstr(attr[i + 1], "none") != 0) {
+ // No uniform scaling
+ p->alignType = NSVG_ALIGN_NONE;
+ } else {
+ // Parse X align
+ if (strstr(attr[i + 1], "xMin") != 0)
+ p->alignX = NSVG_ALIGN_MIN;
+ else if (strstr(attr[i + 1], "xMid") != 0)
+ p->alignX = NSVG_ALIGN_MID;
+ else if (strstr(attr[i + 1], "xMax") != 0)
+ p->alignX = NSVG_ALIGN_MAX;
+ // Parse X align
+ if (strstr(attr[i + 1], "yMin") != 0)
+ p->alignY = NSVG_ALIGN_MIN;
+ else if (strstr(attr[i + 1], "yMid") != 0)
+ p->alignY = NSVG_ALIGN_MID;
+ else if (strstr(attr[i + 1], "yMax") != 0)
+ p->alignY = NSVG_ALIGN_MAX;
+ // Parse meet/slice
+ p->alignType = NSVG_ALIGN_MEET;
+ if (strstr(attr[i + 1], "slice") != 0)
+ p->alignType = NSVG_ALIGN_SLICE;
+ }
+ }
+ }
+ }
+}
+
+static void nsvg__parseGradient(NSVGparser *p, const char **attr, char type) {
+ int i;
+ NSVGgradientData *grad = (NSVGgradientData *)malloc(sizeof(NSVGgradientData));
+ if (grad == NULL)
+ return;
+ memset(grad, 0, sizeof(NSVGgradientData));
+ grad->units = NSVG_OBJECT_SPACE;
+ grad->type = type;
+ if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) {
+ grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
+ grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
+ grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT);
+ grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
+ } else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) {
+ grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
+ grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
+ grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
+ }
+
+ nsvg__xformIdentity(grad->xform);
+
+ for (i = 0; attr[i]; i += 2) {
+ if (strcmp(attr[i], "id") == 0) {
+ strncpy(grad->id, attr[i + 1], 63);
+ grad->id[63] = '\0';
+ } else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "gradientUnits") == 0) {
+ if (strcmp(attr[i + 1], "objectBoundingBox") == 0)
+ grad->units = NSVG_OBJECT_SPACE;
+ else
+ grad->units = NSVG_USER_SPACE;
+ } else if (strcmp(attr[i], "gradientTransform") == 0) {
+ nsvg__parseTransform(grad->xform, attr[i + 1]);
+ } else if (strcmp(attr[i], "cx") == 0) {
+ grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "cy") == 0) {
+ grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "r") == 0) {
+ grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "fx") == 0) {
+ grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "fy") == 0) {
+ grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "x1") == 0) {
+ grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "y1") == 0) {
+ grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "x2") == 0) {
+ grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "y2") == 0) {
+ grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ } else if (strcmp(attr[i], "spreadMethod") == 0) {
+ if (strcmp(attr[i + 1], "pad") == 0)
+ grad->spread = NSVG_SPREAD_PAD;
+ else if (strcmp(attr[i + 1], "reflect") == 0)
+ grad->spread = NSVG_SPREAD_REFLECT;
+ else if (strcmp(attr[i + 1], "repeat") == 0)
+ grad->spread = NSVG_SPREAD_REPEAT;
+ } else if (strcmp(attr[i], "xlink:href") == 0) {
+ const char *href = attr[i + 1];
+ strncpy(grad->ref, href + 1, 62);
+ grad->ref[62] = '\0';
+ }
+ }
+ }
+
+ grad->next = p->gradients;
+ p->gradients = grad;
+}
+
+static void nsvg__parseGradientStop(NSVGparser *p, const char **attr) {
+ NSVGattrib *curAttr = nsvg__getAttr(p);
+ NSVGgradientData *grad;
+ NSVGgradientStop *stop;
+ int i, idx;
+
+ curAttr->stopOffset = 0;
+ curAttr->stopColor = 0;
+ curAttr->stopOpacity = 1.0f;
+
+ for (i = 0; attr[i]; i += 2) {
+ nsvg__parseAttr(p, attr[i], attr[i + 1]);
+ }
+
+ // Add stop to the last gradient.
+ grad = p->gradients;
+ if (grad == NULL)
+ return;
+
+ grad->nstops++;
+ grad->stops = (NSVGgradientStop *)realloc(grad->stops, sizeof(NSVGgradientStop) * grad->nstops);
+ if (grad->stops == NULL)
+ return;
+
+ // Insert
+ idx = grad->nstops - 1;
+ for (i = 0; i < grad->nstops - 1; i++) {
+ if (curAttr->stopOffset < grad->stops[i].offset) {
+ idx = i;
+ break;
+ }
+ }
+ if (idx != grad->nstops - 1) {
+ for (i = grad->nstops - 1; i > idx; i--)
+ grad->stops[i] = grad->stops[i - 1];
+ }
+
+ stop = &grad->stops[idx];
+ stop->color = curAttr->stopColor;
+ stop->color |= (unsigned int)(curAttr->stopOpacity * 255) << 24;
+ stop->offset = curAttr->stopOffset;
+}
+
+static void nsvg__startElement(void *ud, const char *el, const char **attr) {
+ NSVGparser *p = (NSVGparser *)ud;
+
+ if (p->defsFlag) {
+ // Skip everything but gradients in defs
+ if (strcmp(el, "linearGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
+ } else if (strcmp(el, "radialGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
+ } else if (strcmp(el, "stop") == 0) {
+ nsvg__parseGradientStop(p, attr);
+ }
+ return;
+ }
+
+ if (strcmp(el, "g") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseAttribs(p, attr);
+ } else if (strcmp(el, "path") == 0) {
+ if (p->pathFlag) // Do not allow nested paths.
+ return;
+ nsvg__pushAttr(p);
+ nsvg__parsePath(p, attr);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "rect") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseRect(p, attr);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "circle") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseCircle(p, attr);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "ellipse") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseEllipse(p, attr);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "line") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseLine(p, attr);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "polyline") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parsePoly(p, attr, 0);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "polygon") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parsePoly(p, attr, 1);
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "linearGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
+ } else if (strcmp(el, "radialGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
+ } else if (strcmp(el, "stop") == 0) {
+ nsvg__parseGradientStop(p, attr);
+ } else if (strcmp(el, "defs") == 0) {
+ p->defsFlag = 1;
+ } else if (strcmp(el, "svg") == 0) {
+ nsvg__parseSVG(p, attr);
+ }
+}
+
+static void nsvg__endElement(void *ud, const char *el) {
+ NSVGparser *p = (NSVGparser *)ud;
+
+ if (strcmp(el, "g") == 0) {
+ nsvg__popAttr(p);
+ } else if (strcmp(el, "path") == 0) {
+ p->pathFlag = 0;
+ } else if (strcmp(el, "defs") == 0) {
+ p->defsFlag = 0;
+ }
+}
+
+static void nsvg__content(void *ud, const char *s) {
+ NSVG_NOTUSED(ud);
+ NSVG_NOTUSED(s);
+ // empty
+}
+
+static void nsvg__imageBounds(NSVGparser *p, float *bounds) {
+ NSVGshape *shape;
+ shape = p->image->shapes;
+ if (shape == NULL) {
+ bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
+ return;
+ }
+ bounds[0] = shape->bounds[0];
+ bounds[1] = shape->bounds[1];
+ bounds[2] = shape->bounds[2];
+ bounds[3] = shape->bounds[3];
+ for (shape = shape->next; shape != NULL; shape = shape->next) {
+ bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]);
+ bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]);
+ bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]);
+ bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]);
+ }
+}
+
+static float nsvg__viewAlign(float content, float container, int type) {
+ if (type == NSVG_ALIGN_MIN)
+ return 0;
+ else if (type == NSVG_ALIGN_MAX)
+ return container - content;
+ // mid
+ return (container - content) * 0.5f;
+}
+
+static void nsvg__scaleGradient(NSVGgradient *grad, float tx, float ty, float sx, float sy) {
+ float t[6];
+ nsvg__xformSetTranslation(t, tx, ty);
+ nsvg__xformMultiply(grad->xform, t);
+
+ nsvg__xformSetScale(t, sx, sy);
+ nsvg__xformMultiply(grad->xform, t);
+}
+
+static void nsvg__scaleToViewbox(NSVGparser *p, const char *units) {
+ NSVGshape *shape;
+ NSVGpath *path;
+ float tx, ty, sx, sy, us, bounds[4], t[6], avgs;
+ int i;
+ float *pt;
+
+ // Guess image size if not set completely.
+ nsvg__imageBounds(p, bounds);
+
+ if (p->viewWidth == 0) {
+ if (p->image->width > 0) {
+ p->viewWidth = p->image->width;
+ } else {
+ p->viewMinx = bounds[0];
+ p->viewWidth = bounds[2] - bounds[0];
+ }
+ }
+ if (p->viewHeight == 0) {
+ if (p->image->height > 0) {
+ p->viewHeight = p->image->height;
+ } else {
+ p->viewMiny = bounds[1];
+ p->viewHeight = bounds[3] - bounds[1];
+ }
+ }
+ if (p->image->width == 0)
+ p->image->width = p->viewWidth;
+ if (p->image->height == 0)
+ p->image->height = p->viewHeight;
+
+ tx = -p->viewMinx;
+ ty = -p->viewMiny;
+ sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0;
+ sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0;
+ // Unit scaling
+ us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f);
+
+ // Fix aspect ratio
+ if (p->alignType == NSVG_ALIGN_MEET) {
+ // fit whole image into viewbox
+ sx = sy = nsvg__minf(sx, sy);
+ tx += nsvg__viewAlign(p->viewWidth * sx, p->image->width, p->alignX) / sx;
+ ty += nsvg__viewAlign(p->viewHeight * sy, p->image->height, p->alignY) / sy;
+ } else if (p->alignType == NSVG_ALIGN_SLICE) {
+ // fill whole viewbox with image
+ sx = sy = nsvg__maxf(sx, sy);
+ tx += nsvg__viewAlign(p->viewWidth * sx, p->image->width, p->alignX) / sx;
+ ty += nsvg__viewAlign(p->viewHeight * sy, p->image->height, p->alignY) / sy;
+ }
+
+ // Transform
+ sx *= us;
+ sy *= us;
+ avgs = (sx + sy) / 2.0f;
+ for (shape = p->image->shapes; shape != NULL; shape = shape->next) {
+ shape->bounds[0] = (shape->bounds[0] + tx) * sx;
+ shape->bounds[1] = (shape->bounds[1] + ty) * sy;
+ shape->bounds[2] = (shape->bounds[2] + tx) * sx;
+ shape->bounds[3] = (shape->bounds[3] + ty) * sy;
+ for (path = shape->paths; path != NULL; path = path->next) {
+ path->bounds[0] = (path->bounds[0] + tx) * sx;
+ path->bounds[1] = (path->bounds[1] + ty) * sy;
+ path->bounds[2] = (path->bounds[2] + tx) * sx;
+ path->bounds[3] = (path->bounds[3] + ty) * sy;
+ for (i = 0; i < path->npts; i++) {
+ pt = &path->pts[i * 2];
+ pt[0] = (pt[0] + tx) * sx;
+ pt[1] = (pt[1] + ty) * sy;
+ }
+ }
+
+ if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) {
+ nsvg__scaleGradient(shape->fill.gradient, tx, ty, sx, sy);
+ memcpy(t, shape->fill.gradient->xform, sizeof(float) * 6);
+ nsvg__xformInverse(shape->fill.gradient->xform, t);
+ }
+ if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) {
+ nsvg__scaleGradient(shape->stroke.gradient, tx, ty, sx, sy);
+ memcpy(t, shape->stroke.gradient->xform, sizeof(float) * 6);
+ nsvg__xformInverse(shape->stroke.gradient->xform, t);
+ }
+
+ shape->strokeWidth *= avgs;
+ shape->strokeDashOffset *= avgs;
+ for (i = 0; i < shape->strokeDashCount; i++)
+ shape->strokeDashArray[i] *= avgs;
+ }
+}
+
+NSVGimage *nsvgParse(char *input, const char *units, float dpi) {
+ NSVGparser *p;
+ NSVGimage *ret = 0;
+
+ p = nsvg__createParser();
+ if (p == NULL) {
+ return NULL;
+ }
+ p->dpi = dpi;
+
+ nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
+
+ // Scale to viewBox
+ nsvg__scaleToViewbox(p, units);
+
+ ret = p->image;
+ p->image = NULL;
+
+ nsvg__deleteParser(p);
+
+ return ret;
+}
+
+NSVGimage *nsvgParseFromFile(const char *filename, const char *units, float dpi) {
+ FILE *fp = NULL;
+ size_t size;
+ char *data = NULL;
+ NSVGimage *image = NULL;
+
+ fp = fopen(filename, "rb");
+ if (!fp)
+ goto error;
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ data = (char *)malloc(size + 1);
+ if (data == NULL)
+ goto error;
+ if (fread(data, 1, size, fp) != size)
+ goto error;
+ data[size] = '\0'; // Must be null terminated.
+ fclose(fp);
+ image = nsvgParse(data, units, dpi);
+ free(data);
+
+ return image;
error:
- if (fp) fclose(fp);
- if (data) free(data);
- if (image) nsvgDelete(image);
- return NULL;
-}
-
-void nsvgDelete(NSVGimage* image)
-{
- NSVGshape *snext, *shape;
- if (image == NULL) return;
- shape = image->shapes;
- while (shape != NULL) {
- snext = shape->next;
- nsvg__deletePaths(shape->paths);
- nsvg__deletePaint(&shape->fill);
- nsvg__deletePaint(&shape->stroke);
- free(shape);
- shape = snext;
- }
- free(image);
+ if (fp)
+ fclose(fp);
+ if (data)
+ free(data);
+ if (image)
+ nsvgDelete(image);
+ return NULL;
+}
+
+void nsvgDelete(NSVGimage *image) {
+ NSVGshape *snext, *shape;
+ if (image == NULL)
+ return;
+ shape = image->shapes;
+ while (shape != NULL) {
+ snext = shape->next;
+ nsvg__deletePaths(shape->paths);
+ nsvg__deletePaint(&shape->fill);
+ nsvg__deletePaint(&shape->stroke);
+ free(shape);
+ shape = snext;
+ }
+ free(image);
}
#endif
-static int _rnd_count = 9999;
-static float _rnd[] = { 0.39540747,
-0.841546, 0.52073574, 0.80399257, 0.95868486, 0.46164507, 0.5644759, 0.50258803, 0.1953517, 0.40522006, 0.7953865,
-0.7795385, 0.6009604, 0.03921096, 0.56872225, 0.93369347, 0.7019503, 0.5392296, 0.2671585, 0.87286836, 0.28110227,
-0.41505373, 0.8609184, 0.65234584, 0.18079561, 0.1345461, 0.26905555, 0.97823226, 0.9349287, 0.37662244, 0.47883937,
-0.1831086, 0.63446456, 0.2549137, 0.8205819, 0.44705132, 0.7044422, 0.36040744, 0.29616997, 0.60375917, 0.21973382,
-0.094351165, 0.3769042, 0.9975177, 0.6133292, 0.3379986, 0.88620085, 0.83456165, 0.16677794, 0.2749627, 0.28938183,
-0.6274365, 0.058304083, 0.97233975, 0.48520145, 0.9803537, 0.9806276, 0.8683899, 0.62319696, 0.82413876, 0.19258952,
-0.5862436, 0.5676593, 0.8187293, 0.9263807, 0.6122779, 0.14507395, 0.34604672, 0.21862903, 0.121670924, 0.22925124,
-0.34154287, 0.2430596, 0.66339934, 0.6531345, 0.1867511, 0.038149532, 0.8634007, 0.039016694, 0.84279704, 0.24834526,
-0.4344939, 0.8114543, 0.65996605, 0.08724063, 0.8514029, 0.12480451, 0.6621248, 0.76971227, 0.8402282, 0.46642372,
-0.83605236, 0.73721045, 0.47203118, 0.41116965, 0.6334902, 0.52669185, 0.55817497, 0.07113702, 0.0010512439, 0.19292463,
-0.5401541, 0.61593264, 0.045107026, 0.04571145, 0.94783896, 0.3843769, 0.39490476, 0.3192052, 0.29845035, 0.9422042,
-0.11722695, 0.8293732, 0.7804, 0.5757935, 0.7580956, 0.7747893, 0.90769327, 0.73148865, 0.074977815, 0.4874734,
-0.48294914, 0.5763345, 0.37840083, 0.6552472, 0.39319888, 0.6043324, 0.77102846, 0.25222966, 0.019644327, 0.6600592,
-0.4799746, 0.7922636, 0.03796545, 0.64987236, 0.70819116, 0.81856126, 0.7663473, 0.6142546, 0.13940167, 0.46702597,
-0.72989976, 0.34291962, 0.47126192, 0.89802396, 0.34919676, 0.0066791615, 0.95681053, 0.8962376, 0.653074, 0.85870093,
-0.6189986, 0.8266863, 0.9961592, 0.5135778, 0.7099755, 0.9638197, 0.2375318, 0.3898598, 0.65251255, 0.34350657,
-0.6133485, 0.14267509, 0.29956087, 0.6383911, 0.4622296, 0.3249633, 0.79140776, 0.13052759, 0.8676024, 0.93953437,
-0.008441999, 0.2934387, 0.592087, 0.6079518, 0.75757366, 0.14002953, 0.10507256, 0.48037684, 0.30605045, 0.38651973,
-0.64752185, 0.8747908, 0.59915566, 0.1609434, 0.04106063, 0.65328825, 0.79610443, 0.5243876, 0.9398969, 0.7443715,
-0.5810295, 0.3764875, 0.961742, 0.7958951, 0.8536775, 0.58722466, 0.043358732, 0.8328708, 0.43579438, 0.024233455,
-0.21527143, 0.8262829, 0.028635254, 0.71353966, 0.85025895, 0.3255599, 0.23459937, 0.38820738, 0.7560042, 0.569946,
-0.8587471, 0.75715494, 0.083809346, 0.26599285, 0.6959847, 0.73855764, 0.54351944, 0.13861747, 0.59733045, 0.80894136,
-0.52885884, 0.26702014, 0.1906307, 0.123230904, 0.35850486, 0.6319545, 0.3316967, 0.7961919, 0.7542743, 0.17034897,
-0.0966708, 0.27220175, 0.04458247, 0.28181702, 0.1712483, 0.82123893, 0.8461555, 0.88561594, 0.3106845, 0.7155007,
-0.4186889, 0.40789708, 0.76838344, 0.36995092, 0.8856244, 0.82387453, 0.29267815, 0.69574916, 0.099910386, 0.11511985,
-0.04370523, 0.9047413, 0.23554033, 0.62685305, 0.4953746, 0.9482513, 0.63565224, 0.9054043, 0.3550348, 0.21830441,
-0.9938632, 0.4384075, 0.633933, 0.5856552, 0.47327515, 0.58654535, 0.71257246, 0.80199236, 0.09474454, 0.8747458,
-0.8924021, 0.6579035, 0.82793295, 0.88182974, 0.39025244, 0.12096177, 0.4986367, 0.8206798, 0.23760653, 0.53463036,
-0.33927637, 0.6359475, 0.6962815, 0.6391545, 0.12664375, 0.19192953, 0.036661416, 0.41772944, 0.7864424, 0.222997,
-0.18558672, 0.9407512, 0.5305812, 0.092380084, 0.7216375, 0.9802814, 0.77396405, 0.18272822, 0.89667577, 0.29907903,
-0.11130205, 0.4906858, 0.60100466, 0.22516462, 0.22271773, 0.38580173, 0.07680829, 0.3537106, 0.23660058, 0.37441283,
-0.4496146, 0.81497246, 0.6677978, 0.82040447, 0.879028, 0.35791573, 0.742126, 0.9947786, 0.45901147, 0.28134564,
-0.54988396, 0.29484302, 0.015549939, 0.87174755, 0.68915904, 0.9516509, 0.12732233, 0.7355529, 0.16019227, 0.40997103,
-0.34699774, 0.31590846, 0.924004, 0.93852746, 0.4233283, 0.84859055, 0.034942873, 0.47111684, 0.41643673, 0.740842,
-0.115121245, 0.68295085, 0.18112887, 0.41202956, 0.77338237, 0.3706143, 0.27295336, 0.7101767, 0.21335205, 0.36372176,
-0.2381554, 0.7791855, 0.72371674, 0.6153301, 0.7491951, 0.816459, 0.47513586, 0.7292571, 0.5360056, 0.2710668,
-0.25847942, 0.3412554, 0.19351831, 0.8266295, 0.0274151, 0.13370614, 0.8909684, 0.72927034, 0.39707616, 0.030437447,
-0.32297286, 0.27100918, 0.57834184, 0.71816945, 0.16622439, 0.8669331, 0.11371415, 0.6035204, 0.09836516, 0.31854475,
-0.6786976, 0.41714564, 0.5222008, 0.7964705, 0.17181565, 0.56781226, 0.5921917, 0.30867395, 0.1893324, 0.6068693,
-0.37345472, 0.3056858, 0.9351113, 0.14536993, 0.4823626, 0.7738658, 0.4894325, 0.35449934, 0.38461447, 0.6396763,
-0.4796459, 0.54368305, 0.31310055, 0.18291461, 0.040748898, 0.9671462, 0.20084366, 0.0055472897, 0.4491057, 0.882262,
-0.7027449, 0.87161547, 0.6308919, 0.21746083, 0.59236926, 0.8413338, 0.81905454, 0.3970478, 0.6548139, 0.45960286,
-0.5415144, 0.58229446, 0.539938, 0.7902069, 0.6569827, 0.017287076, 0.33589792, 0.4329719, 0.23580688, 0.39235854,
-0.3775006, 0.7592148, 0.2189059, 0.45868888, 0.83889884, 0.13501453, 0.10404509, 0.3392862, 0.7557216, 0.20466943,
-0.36696857, 0.5866444, 0.85956824, 0.3070704, 0.9041244, 0.5018392, 0.67479384, 0.7176504, 0.5530007, 0.6410288,
-0.9548113, 0.092384726, 0.69968545, 0.92501163, 0.09816185, 0.89735144, 0.0037450776, 0.52289367, 0.5259319, 0.023461822,
-0.6312483, 0.7678718, 0.7697404, 0.05674718, 0.5047614, 0.9435301, 0.6527096, 0.17220303, 0.37856197, 0.45735472,
-0.7372887, 0.47976837, 0.6413262, 0.45014447, 0.09263428, 0.95487, 0.7227262, 0.23286755, 0.8860825, 0.15514348,
-0.34249324, 0.61824745, 0.8799712, 0.59477806, 0.43754727, 0.28511587, 0.059529364, 0.2938943, 0.36052704, 0.9415474,
-0.13126945, 0.5811514, 0.8133543, 0.7322598, 0.5734211, 0.5990968, 0.816904, 0.80282104, 0.802309, 0.96059436,
-0.8491296, 0.50259084, 0.33908847, 0.09564596, 0.9037401, 0.4750429, 0.45105854, 0.24954097, 0.8323773, 0.14329186,
-0.17462522, 0.77087754, 0.63681114, 0.3707884, 0.6809686, 0.013000839, 0.8879006, 0.17496233, 0.61919993, 0.21964556,
-0.8840007, 0.3588153, 0.81167597, 0.43701455, 0.32608527, 0.15613726, 0.666414, 0.9090664, 0.87672335, 0.4935375,
-0.13796596, 0.9199052, 0.43055856, 0.9254882, 0.30601385, 0.8399024, 0.279159, 0.78432524, 0.69103795, 0.9625043,
-0.83405733, 0.8099884, 0.46151695, 0.2172352, 0.7669222, 0.3603919, 0.9443403, 0.44256592, 0.0512912, 0.5604203,
-0.7111962, 0.64194167, 0.18362112, 0.5826634, 0.07659364, 0.49031433, 0.6909148, 0.9020739, 0.7695607, 0.7476028,
-0.80862886, 0.5419922, 0.3728176, 0.33883983, 0.005325912, 0.25472003, 0.34031895, 0.711323, 0.064774565, 0.8410662,
-0.73384184, 0.10357534, 0.48392436, 0.65669554, 0.38558826, 0.07401231, 0.8972984, 0.5944408, 0.67009234, 0.96569335,
-0.21179698, 0.22384812, 0.8577752, 0.31630307, 0.7823413, 0.49602425, 0.7362841, 0.84789515, 0.84889454, 0.8156995,
-0.14898759, 0.3770851, 0.01476456, 0.94343513, 0.15387547, 0.29206514, 0.43717077, 0.12267711, 0.21190928, 0.5122022,
-0.020072967, 0.23301727, 0.37779135, 0.21022503, 0.82657844, 0.60762084, 0.15801735, 0.52692556, 0.19707517, 0.0025813282,
-0.59301597, 0.09647403, 0.23198159, 0.80386734, 0.5358059, 0.58478075, 0.684217, 0.056514528, 0.5564985, 0.50930166,
-0.51843596, 0.4924238, 0.8624285, 0.24907504, 0.6920786, 0.35675675, 0.08881078, 0.5404892, 0.5028201, 0.0935231,
-0.63684154, 0.77462125, 0.38253152, 0.15789017, 0.94562036, 0.97877973, 0.84605676, 0.64755017, 0.48972467, 0.17472044,
-0.3380069, 0.2093585, 0.65081996, 0.8463132, 0.22268358, 0.052513562, 0.1451035, 0.21089722, 0.40762928, 0.5690947,
-0.60784817, 0.38065624, 0.56617856, 0.70260763, 0.99376625, 0.52764916, 0.37058878, 0.1287163, 0.51814646, 0.4698217,
-0.5188101, 0.61752814, 0.024105478, 0.103552066, 0.3657398, 0.81839466, 0.7139425, 0.07409142, 0.858247, 0.55702615,
-0.738724, 0.03666682, 0.56678987, 0.38177812, 0.17129473, 0.30907747, 0.8416038, 0.016115308, 0.02639147, 0.639565,
-0.21165326, 0.87791353, 0.13285992, 0.9337254, 0.48567492, 0.2561853, 0.20844269, 0.6799239, 0.16412394, 0.41797122,
-0.60819095, 0.71734047, 0.12940371, 0.019902974, 0.6559104, 0.7204788, 0.18525302, 0.5472679, 0.4805734, 0.4042889,
-0.33857107, 0.07101207, 0.35265025, 0.85060316, 0.8303707, 0.57118136, 0.8138664, 0.18440045, 0.5313129, 0.68468875,
-0.68604535, 0.35447347, 0.10232483, 0.8785814, 0.25816843, 0.6408965, 0.48466823, 0.09038009, 0.6178771, 0.10955451,
-0.609952, 0.034018606, 0.9099675, 0.44027576, 0.9488352, 0.021383535, 0.9072631, 0.5468869, 0.72586775, 0.45081598,
-0.12382444, 0.29433593, 0.5355419, 0.62210256, 0.30099395, 0.14064118, 0.5252633, 0.28225678, 0.10335469, 0.91449356,
-0.44231892, 0.024042243, 0.14861101, 0.47943518, 0.7319259, 0.2537175, 0.6150156, 0.25082228, 0.76173455, 0.01501382,
-0.23581055, 0.09487294, 0.9293908, 0.3710189, 0.7943369, 0.30455244, 0.1610446, 0.9123745, 0.90176797, 0.80898714,
-0.66391826, 0.2669795, 0.4585327, 0.08049692, 0.5608643, 0.3917094, 0.8189315, 0.48022225, 0.5775875, 0.11752723,
-0.11563321, 0.20241146, 0.9870254, 0.70338356, 0.6672356, 0.5859097, 0.88540757, 0.4305323, 0.7083498, 0.69511765,
-0.4063679, 0.6564408, 0.7851523, 0.71085393, 0.21500541, 0.028951503, 0.36494514, 0.16452302, 0.8277657, 0.9964415,
-0.9795966, 0.6128888, 0.38048878, 0.29436752, 0.25057533, 0.17533945, 0.56550956, 0.06811409, 0.9185709, 0.3402165,
-0.43478596, 0.13479339, 0.6732348, 0.64420736, 0.8993806, 0.033399098, 0.10784754, 0.22600721, 0.7037833, 0.20842715,
-0.41914487, 0.7305123, 0.20402466, 0.2066503, 0.40261927, 0.007477421, 0.48182714, 0.74767876, 0.8654915, 0.5319128,
-0.026764244, 0.6544085, 0.6524566, 0.58114594, 0.13793063, 0.50274444, 0.82192266, 0.6926579, 0.45280823, 0.49189615,
-0.020400187, 0.8172935, 0.51196146, 0.36813334, 0.26033172, 0.27157453, 0.983206, 0.140945, 0.81147337, 0.18160632,
-0.92110395, 0.13893794, 0.46073973, 0.6193385, 0.5772967, 0.2490843, 0.40886414, 0.1738385, 0.89174825, 0.24309792,
-0.6935123, 0.8178308, 0.20262258, 0.38665804, 0.31345224, 0.78037745, 0.48233682, 0.09208888, 0.50627667, 0.3966362,
-0.21147643, 0.41518968, 0.77319896, 0.21188715, 0.18802696, 0.60185134, 0.21855086, 0.8358913, 0.94631857, 0.13104475,
-0.024271427, 0.34088212, 0.9362054, 0.6838852, 0.61080885, 0.8878263, 0.1936688, 0.03311803, 0.0038492912, 0.88884634,
-0.09388026, 0.64808416, 0.8009096, 0.2097103, 0.79838383, 0.20256937, 0.61467093, 0.1253034, 0.054681093, 0.47995427,
-0.7892377, 0.8911171, 0.6346683, 0.41483715, 0.9701299, 0.5059143, 0.36573896, 0.24885257, 0.43131158, 0.97544533,
-0.03053343, 0.57297283, 0.2275199, 0.7607035, 0.21882649, 0.3526302, 0.8816254, 0.5187374, 0.77584916, 0.42562595,
-0.58670866, 0.44921878, 0.08823959, 0.6174303, 0.30275592, 0.5633923, 0.61428005, 0.56348866, 0.41350332, 0.9854576,
-0.9871804, 0.093247466, 0.7812102, 0.4663643, 0.34180707, 0.13315432, 0.70621383, 0.52136827, 0.7137553, 0.10489457,
-0.52208734, 0.94481623, 0.60180646, 0.028403986, 0.8583129, 0.5209074, 0.42056426, 0.04020609, 0.9908838, 0.44575363,
-0.32094392, 0.09593353, 0.34945422, 0.62905514, 0.89324564, 0.3400189, 0.80287755, 0.017237967, 0.112081215, 0.40673763,
-0.8916342, 0.80225027, 0.83534926, 0.44585398, 0.98826486, 0.93728596, 0.79176265, 0.7611556, 0.41889647, 0.08567218,
-0.64641637, 0.3602572, 0.80498207, 0.6709546, 0.9035386, 0.64189243, 0.84741235, 0.0598356, 0.7591174, 0.7818485,
-0.142828, 0.574074, 0.5726049, 0.96774966, 0.6645137, 0.8912469, 0.74379325, 0.15215507, 0.5731187, 0.0017881524,
-0.3302768, 0.6889758, 0.40928704, 0.30701768, 0.21326037, 0.71983707, 0.10946698, 0.1559525, 0.040139113, 0.92102695,
-0.7291448, 0.6594087, 0.62130964, 0.9052116, 0.79933727, 0.9606867, 0.29095143, 0.6784996, 0.72551656, 0.2513532,
-0.49260658, 0.74304193, 0.25812054, 0.33023268, 0.2639096, 0.31756023, 0.22964539, 0.86759955, 0.7813403, 0.097017966,
-0.19349271, 0.63960755, 0.18803692, 0.4171083, 0.7553954, 0.95744056, 0.9509702, 0.4979644, 0.45769426, 0.18370152,
-0.53242546, 0.69145983, 0.019696489, 0.8380905, 0.052703734, 0.48341933, 0.95276433, 0.6673932, 0.16841243, 0.70382696,
-0.6002955, 0.06529366, 0.42663854, 0.32176548, 0.50918156, 0.58723485, 0.4308553, 0.079054326, 0.04310807, 0.89570016,
-0.4901917, 0.24186741, 0.3746122, 0.94312114, 0.72753423, 0.08953723, 0.47137174, 0.20420133, 0.14981624, 0.8418967,
-0.009716521, 0.79298705, 0.22080535, 0.541815, 0.71892774, 0.80114675, 0.72334546, 0.42003006, 0.27752897, 0.7804903,
-0.36479586, 0.56225216, 0.69918716, 0.07751329, 0.4967225, 0.12819904, 0.212969, 0.86627144, 0.90792674, 0.16816054,
-0.5265852, 0.8719159, 0.45485634, 0.56199414, 0.6935098, 0.29055804, 0.31684762, 0.07657534, 0.11055623, 0.9631665,
-0.012047576, 0.74856305, 0.517577, 0.32651573, 0.69411045, 0.80730844, 0.8444883, 0.88482356, 0.60283774, 0.7080349,
-0.8638894, 0.010825248, 0.80152535, 0.26261777, 0.53090423, 0.92793953, 0.54268026, 0.29709893, 0.44639865, 0.5993352,
-0.8765682, 0.6051003, 0.2962746, 0.9816557, 0.31531146, 0.13780066, 0.3381307, 0.6588112, 0.84830517, 0.4283697,
-0.48429912, 0.6467701, 0.30947384, 0.31436247, 0.7684427, 0.6162329, 0.044675153, 0.3726714, 0.38340282, 0.689414,
-0.28371072, 0.32814547, 0.26343372, 0.19989188, 0.30427113, 0.51576, 0.07039049, 0.19223855, 0.031089857, 0.7655703,
-0.7478778, 0.019748688, 0.63017666, 0.511221, 0.08659828, 0.40694728, 0.45228842, 0.53592134, 0.011204251, 0.5563098,
-0.46917772, 0.18567711, 0.036518365, 0.17446801, 0.22373573, 0.21711932, 0.7013514, 0.48716292, 0.49417505, 0.9146714,
-0.88326436, 0.17000887, 0.9136961, 0.7569846, 0.3156245, 0.54842275, 0.34166658, 0.09638273, 0.67738456, 0.7995515,
-0.06741016, 0.14589214, 0.62772137, 0.08273488, 0.680492, 0.46455044, 0.016593413, 0.7982528, 0.22776419, 0.36149544,
-0.16394442, 0.50875384, 0.36146715, 0.827093, 0.22023632, 0.098033614, 0.2916271, 0.088965714, 0.9761561, 0.08715181,
-0.8144086, 0.5832276, 0.6980635, 0.11641844, 0.8823059, 0.5778689, 0.106052585, 0.8731921, 0.19559653, 0.5381755,
-0.06528069, 0.3559057, 0.8585367, 0.21165277, 0.48889965, 0.32328558, 0.55795574, 0.95378345, 0.49397606, 0.7591853,
-0.20052591, 0.9030986, 0.25939873, 0.13267961, 0.750727, 0.37451053, 0.8085417, 0.086603075, 0.5367483, 0.21759088,
-0.25679567, 0.25270087, 0.120226584, 0.59023273, 0.9851429, 0.48418257, 0.44782865, 0.51130295, 0.20042898, 0.102623075,
-0.35849786, 0.14340132, 0.6026563, 0.68958867, 0.29621476, 0.8080387, 0.6502171, 0.14981438, 0.3381934, 0.8969507,
-0.54007787, 0.33784363, 0.59498966, 0.21697083, 0.8866259, 0.91130996, 0.32382888, 0.5653839, 0.36569145, 0.5077954,
-0.76932716, 0.01944951, 0.3364438, 0.97800565, 0.28137985, 0.8125798, 0.2356791, 0.268304, 0.22650987, 0.00471706,
-0.8754569, 0.04665282, 0.7533545, 0.39135298, 0.40068746, 0.05712457, 0.3004423, 0.56981003, 0.8364648, 0.9426883,
-0.7242934, 0.65872735, 0.7484097, 0.63979757, 0.677513, 0.91895205, 0.6577112, 0.90325576, 0.70360684, 0.07383294,
-0.1603537, 0.88244474, 0.14561148, 0.6926336, 0.3332959, 0.33904833, 0.80695754, 0.62465066, 0.40820882, 0.48363495,
-0.5723596, 0.38191313, 0.9233045, 0.33347633, 0.021493766, 0.49342504, 0.5844891, 0.20363668, 0.81628335, 0.82950133,
-0.6108677, 0.75401884, 0.728919, 0.42300317, 0.7835019, 0.11059984, 0.2710398, 0.6966462, 0.30049264, 0.3624278,
-0.1548686, 0.33242336, 0.56469715, 0.15267694, 0.84436333, 0.9930122, 0.9010413, 0.06072089, 0.058057077, 0.061639126,
-0.25016704, 0.6757917, 0.16160122, 0.3528299, 0.37032866, 0.34238032, 0.7354228, 0.41493335, 0.6183038, 0.18408795,
-0.3344629, 0.45407453, 0.08697238, 0.8741055, 0.46296528, 0.40633488, 0.1535257, 0.7226083, 0.90913165, 0.22269607,
-0.068008505, 0.1103113, 0.32415798, 0.045781024, 0.32876635, 0.23993625, 0.817216, 0.77062756, 0.48911297, 0.028481547,
-0.5923837, 0.52376825, 0.14557959, 0.7546443, 0.5793343, 0.935076, 0.5924176, 0.37608913, 0.05267449, 0.44112164,
-0.37517703, 0.85610646, 0.078342445, 0.11640469, 0.02796489, 0.70079404, 0.24545097, 0.69059163, 0.68971163, 0.43802848,
-0.83948654, 0.17843302, 0.15158923, 0.835361, 0.99363065, 0.13985574, 0.3516337, 0.115820184, 0.02406358, 0.13039242,
-0.5251643, 0.96479523, 0.92582035, 0.58982223, 0.59170425, 0.8106947, 0.30849496, 0.33232814, 0.2947712, 0.5278893,
-0.8139172, 0.77743655, 0.6699338, 0.46801004, 0.84751904, 0.21190204, 0.031968854, 0.2077533, 0.017816134, 0.62797225,
-0.99448526, 0.12662433, 0.080915935, 0.05108449, 0.18899502, 0.41395068, 0.372179, 0.3102186, 0.7610136, 0.43947858,
-0.5834423, 0.47659743, 0.35202554, 0.9222821, 0.9159573, 0.4103818, 0.9302861, 0.4885202, 0.52470046, 0.21727021,
-0.39229912, 0.91312283, 0.39582044, 0.16182233, 0.62411124, 0.062049974, 0.5084992, 0.6835792, 0.98784196, 0.78172857,
-0.10788689, 0.1438804, 0.09800406, 0.3960913, 0.13590716, 0.39854, 0.8838793, 0.8747359, 0.40082723, 0.17775355,
-0.43851566, 0.99827635, 0.5713145, 0.8552926, 0.94444704, 0.33731982, 0.42541102, 0.74765176, 0.55205274, 0.43713725,
-0.28161594, 0.5434486, 0.68305284, 0.80054593, 0.23567316, 0.08136242, 0.7308039, 0.9190936, 0.42697325, 0.12694505,
-0.9054515, 0.6885998, 0.32237664, 0.97928506, 0.33159167, 0.43956187, 0.3785934, 0.9559342, 0.7863749, 0.5174173,
-0.5265025, 0.05555021, 0.08769297, 0.3469469, 0.77875453, 0.39402276, 0.34180835, 0.5405278, 0.21737531, 0.2867914,
-0.636639, 0.76084745, 0.13152646, 0.5507047, 0.50011265, 0.5644382, 0.46082756, 0.29745814, 0.16041815, 0.054544732,
-0.6677361, 0.9647857, 0.44776264, 0.27388218, 0.27230206, 0.74991584, 0.67589974, 0.59202945, 0.52370095, 0.50488514,
-0.9587264, 0.46947676, 0.9612768, 0.034635436, 0.91063476, 0.22606573, 0.45575568, 0.33610594, 0.02179139, 0.8416504,
-0.7395541, 0.19027609, 0.7017183, 0.14018182, 0.49030608, 0.14460404, 0.55707335, 0.7716719, 0.47917238, 0.76715344,
-0.9787343, 0.08113525, 0.7955161, 0.7318302, 0.8496812, 0.5617168, 0.60778755, 0.81381077, 0.07464484, 0.028838681,
-0.718123, 0.74977887, 0.016826851, 0.71249014, 0.32806498, 0.16716221, 0.7995706, 0.096891016, 0.64007, 0.27404693,
-0.10868255, 0.12472161, 0.27566674, 0.31876773, 0.31499064, 0.47746003, 0.2630674, 0.30758083, 0.78357613, 0.12769802,
-0.1928425, 0.90422785, 0.112857096, 0.7565475, 0.5261508, 0.8775912, 0.6739607, 0.22944665, 0.18495426, 0.3489179,
-0.61827815, 0.6419449, 0.2614611, 0.9929527, 0.12352738, 0.98977524, 0.17344923, 0.9892281, 0.81211686, 0.32314387,
-0.34503344, 0.46018234, 0.13160191, 0.20512545, 0.65847087, 0.8540127, 0.8054685, 0.47674835, 0.41683954, 0.37222117,
-0.29864943, 0.30020675, 0.03023468, 0.94694686, 0.8359962, 0.8138952, 0.63692176, 0.26027933, 0.18633933, 0.45047382,
-0.49320155, 0.570124, 0.91193676, 0.2911521, 0.65576875, 0.46673766, 0.8632605, 0.28271404, 0.19524036, 0.32521543,
-0.30401078, 0.27383924, 0.495464, 0.46043226, 0.7826646, 0.7326602, 0.7726259, 0.90773165, 0.09807661, 0.6721381,
-0.07212267, 0.1972123, 0.8126071, 0.8127331, 0.05026847, 0.3180714, 0.6117102, 0.31451428, 0.15695652, 0.30963218,
-0.35285345, 0.9131699, 0.8028888, 0.36164302, 0.8299423, 0.7749095, 0.54824555, 0.8404498, 0.5493567, 0.19173324,
-0.9907522, 0.5227545, 0.281508, 0.091624096, 0.06821037, 0.024810186, 0.80474275, 0.5698024, 0.16428226, 0.10333604,
-0.04126928, 0.7291901, 0.16220273, 0.5142012, 0.37835112, 0.29598927, 0.75751686, 0.09920368, 0.24088362, 0.33769736,
-0.85502744, 0.5487462, 0.12575752, 0.8856082, 0.972362, 0.3908409, 0.47095042, 0.13382097, 0.63048995, 0.007755094,
-0.18441458, 0.9321761, 0.35837498, 0.9063434, 0.6813859, 0.5493682, 0.9157043, 0.720983, 0.7445227, 0.025458287,
-0.5133287, 0.041907787, 0.15023202, 0.053620476, 0.2683629, 0.6236633, 0.75096714, 0.28868756, 0.98329186, 0.5339531,
-0.017392641, 0.4490419, 0.5995662, 0.21165931, 0.3367058, 0.44200596, 0.39699697, 0.39589983, 0.11926211, 0.6773695,
-0.5538598, 0.6709218, 0.93931246, 0.15652716, 0.9189215, 0.10909318, 0.37081516, 0.25585935, 0.83281535, 0.82898295,
-0.38028497, 0.03653382, 0.35468096, 0.21542533, 0.8243687, 0.81311965, 0.39851424, 0.07213704, 0.61724526, 0.34869868,
-0.63987374, 0.18226288, 0.15052907, 0.096536905, 0.99036247, 0.73537266, 0.3326099, 0.14671567, 0.5696376, 0.2393799,
-0.15237123, 0.5198045, 0.6017209, 0.067153245, 0.47159854, 0.84240687, 0.1025953, 0.99370486, 0.134699, 0.15926972,
-0.25284818, 0.4951078, 0.45587218, 0.15430894, 0.15366808, 0.9808588, 0.094360925, 0.38414088, 0.3872906, 0.52358615,
-0.043491747, 0.32485992, 0.7786546, 0.7705634, 0.037495736, 0.37159687, 0.5203927, 0.8427756, 0.16616471, 0.18354878,
-0.7764833, 0.22409947, 0.6862218, 0.59343547, 0.6766117, 0.8604805, 0.4348129, 0.2875277, 0.7438268, 0.9819619,
-0.7105244, 0.4048094, 0.937438, 0.45797554, 0.09585048, 0.14476593, 0.7263907, 0.9962201, 0.9428688, 0.009503636,
-0.6410118, 0.94846904, 0.7594251, 0.04605143, 0.19588815, 0.8275113, 0.7411499, 0.83115745, 0.02965751, 0.10000168,
-0.32201412, 0.25981972, 0.82754016, 0.95115024, 0.38278645, 0.02874871, 0.808886, 0.8624367, 0.47769725, 0.29318756,
-0.5460459, 0.8068332, 0.6403141, 0.4053287, 0.8130618, 0.63868237, 0.3874219, 0.320679, 0.67471296, 0.8927298,
-0.64520615, 0.5241726, 0.89990675, 0.15666108, 0.54253703, 0.82801425, 0.46467438, 0.64017034, 0.39754733, 0.8491004,
-0.11933059, 0.60365546, 0.25787023, 0.6438251, 0.65994775, 0.45070463, 0.57726926, 0.98628783, 0.075189106, 0.06710178,
-0.33587992, 0.863954, 0.51852286, 0.64968127, 0.46345773, 0.83417857, 0.30815494, 0.35409638, 0.23298964, 0.5572058,
-0.4400894, 0.4204709, 0.1564445, 0.13692771, 0.4547955, 0.7978415, 0.35991296, 0.67087907, 0.4086132, 0.5547722,
-0.56407434, 0.16871567, 0.46488938, 0.62859684, 0.17385697, 0.94239044, 0.548963, 0.996489, 0.74538094, 0.36235714,
-0.061413143, 0.40113407, 0.24548991, 0.6076112, 0.5568499, 0.78125215, 0.005649717, 0.2502255, 0.69320333, 0.70835847,
-0.5198593, 0.110578, 0.4071807, 0.84034157, 0.40901098, 0.6988597, 0.44721094, 0.12094251, 0.1890296, 0.86210626,
-0.09079167, 0.90639013, 0.5776746, 0.5204169, 0.50302744, 0.16716424, 0.39906463, 0.8899261, 0.47582427, 0.52106726,
-0.2852156, 0.31166598, 0.6087155, 0.87063247, 0.49579263, 0.03895533, 0.174981, 0.5488333, 0.5800778, 0.67354333,
-0.7921918, 0.10968746, 0.97767574, 0.70025474, 0.034912895, 0.45349634, 0.761535, 0.6245478, 0.21958585, 0.47499728,
-0.4951795, 0.42802048, 0.80745935, 0.8832747, 0.27156547, 0.15502298, 0.8234595, 0.725073, 0.10458374, 0.38968566,
-0.38218752, 0.11572367, 0.77440125, 0.17213607, 0.42314288, 0.2081933, 0.5018625, 0.5365482, 0.3445489, 0.37005565,
-0.5238787, 0.8983776, 0.5408647, 0.51548624, 0.06991447, 0.9811042, 0.9287144, 0.8774199, 0.48550403, 0.04953112,
-0.40562928, 0.7745168, 0.6703402, 0.00082698837, 0.025887761, 0.8571951, 0.5042066, 0.7254408, 0.59906703, 0.34076965,
-0.21549584, 0.449908, 0.44424957, 0.19039217, 0.29135585, 0.67646813, 0.33528623, 0.80553967, 0.27711186, 0.8267196,
-0.95163375, 0.22498675, 0.2799989, 0.8495302, 0.9511186, 0.5968019, 0.8871558, 0.2919731, 0.8133602, 0.29046127,
-0.22630857, 0.9460396, 0.23956898, 0.05505262, 0.98405635, 0.60767066, 0.4453835, 0.77357423, 0.14624831, 0.5659478,
-0.7039867, 0.7764218, 0.9374812, 0.0037792725, 0.1545598, 0.073970705, 0.45412806, 0.35047254, 0.2241304, 0.39344636,
-0.645818, 0.12317476, 0.600308, 0.65878445, 0.09789734, 0.18064253, 0.49451795, 0.82080996, 0.049708407, 0.42908588,
-0.9700393, 0.2122335, 0.9120806, 0.30860576, 0.11446109, 0.26945624, 0.21033902, 0.38919696, 0.20633578, 0.6836851,
-0.23108464, 0.56171197, 0.6592914, 0.7111641, 0.122732915, 0.175212, 0.28750554, 0.2762196, 0.69497037, 0.87714785,
-0.14267384, 0.53668326, 0.06784272, 0.41991386, 0.6446433, 0.10313381, 0.34573162, 0.58078456, 0.9571553, 0.8034138,
-0.11315275, 0.62457347, 0.7238658, 0.71716243, 0.59590846, 0.4917532, 0.8643412, 0.62887543, 0.88931817, 0.8851036,
-0.86363167, 0.064931095, 0.14413676, 0.54044527, 0.16236171, 0.084106006, 0.4638834, 0.8891439, 0.5360515, 0.9226853,
-0.893137, 0.21829833, 0.12583959, 0.17256053, 0.28641203, 0.4333561, 0.14439079, 0.49216673, 0.6639625, 0.011327274,
-0.9237246, 0.62955445, 0.43204167, 0.40292194, 0.5705324, 0.6065112, 0.83784616, 0.94212896, 0.115255654, 0.6309797,
-0.3108708, 0.6586301, 0.38690144, 0.8098668, 0.013516203, 0.07774274, 0.39254647, 0.52739745, 0.25755215, 0.5605373,
-0.6392504, 0.4565877, 0.044733036, 0.034469932, 0.91027683, 0.8948544, 0.4987339, 0.5513053, 0.4307504, 0.16255233,
-0.3473624, 0.3721745, 0.96491295, 0.8779909, 0.961379, 0.2340772, 0.6328894, 0.7412148, 0.9699129, 0.55585057,
-0.24625985, 0.52175444, 0.77388823, 0.9050718, 0.61181456, 0.23450689, 0.8313969, 0.31597278, 0.15904433, 0.20866929,
-0.04080962, 0.6169933, 0.23461457, 0.1034252, 0.37207687, 0.4671369, 0.58482146, 0.39757174, 0.4926451, 0.67567796,
-0.107777245, 0.28654084, 0.5113785, 0.9527033, 0.28361735, 0.9386963, 0.6937171, 0.50891054, 0.84848785, 0.779439,
-0.44485334, 0.65133166, 0.55748457, 0.7017016, 0.3142774, 0.11749596, 0.68269944, 0.13966125, 0.42265537, 0.6757699,
-0.06345752, 0.18276113, 0.39226097, 0.2220811, 0.12174272, 0.7303691, 0.13755992, 0.8614878, 0.50591403, 0.4942421,
-0.64925575, 0.23531766, 0.24856968, 0.29423487, 0.44807333, 0.959719, 0.010375906, 0.82118493, 0.6214544, 0.67311823,
-0.5407898, 0.3224864, 0.46748495, 0.37960532, 0.76381594, 0.38947794, 0.05950873, 0.53291297, 0.7891478, 0.2545809,
-0.7844374, 0.44516018, 0.97491634, 0.81687516, 0.61222047, 0.9250161, 0.89427984, 0.28929746, 0.83096063, 0.5532483,
-0.8011364, 0.8322293, 0.0029964554, 0.35424575, 0.13018323, 0.20953566, 0.402762, 0.2632497, 0.25362825, 0.3545584,
-0.10712006, 0.8615145, 0.51820683, 0.7495371, 0.13498017, 0.74097115, 0.7152762, 0.0126556605, 0.45826513, 0.73226476,
-0.67086035, 0.6046469, 0.07234, 0.25133318, 0.70980465, 0.20409557, 0.2604013, 0.43169454, 0.6820144, 0.5230572,
-0.065439165, 0.72107846, 0.99022436, 0.06820616, 0.87198186, 0.70856047, 0.31948993, 0.11323921, 0.24942209, 0.5542803,
-0.9867159, 0.79625905, 0.27928472, 0.4345894, 0.14746083, 0.9229229, 0.9269534, 0.22537923, 0.681895, 0.8712493,
-0.20973994, 0.8816242, 0.83103234, 0.098695815, 0.88238794, 0.19648944, 0.75988936, 0.75166327, 0.64444107, 0.9260877,
-0.94913435, 0.9710675, 0.5812353, 0.7305711, 0.28911924, 0.3860416, 0.87129015, 0.45000067, 0.87755525, 0.42641973,
-0.4214812, 0.60203695, 0.7632336, 0.90398484, 0.74554884, 0.8746013, 0.32536224, 0.6377506, 0.10387234, 0.7868817,
-0.2771422, 0.035022065, 0.74979955, 0.8107651, 0.31331727, 0.18381497, 0.8900461, 0.89152855, 0.18581823, 0.6754924,
-0.9486711, 0.5678266, 0.4687981, 0.32333443, 0.60514593, 0.015648454, 0.21502374, 0.5487136, 0.14547014, 0.76141924,
-0.05163277, 0.4769527, 0.34782398, 0.25547525, 0.44976813, 0.607703, 0.11839061, 0.9270475, 0.35314697, 0.007786621,
-0.8711272, 0.12213872, 0.64779097, 0.8575594, 0.64894545, 0.9141123, 0.22126794, 0.77047014, 0.4172538, 0.10530428,
-0.4959955, 0.97976166, 0.26418245, 0.20206283, 0.47774863, 0.85365456, 0.13323887, 0.43989918, 0.29883888, 0.7299004,
-0.65957755, 0.7766486, 0.49228048, 0.34245312, 0.7352489, 0.8001895, 0.6871981, 0.49432427, 0.360997, 0.70561427,
-0.06542435, 0.96299857, 0.5383816, 0.1780316, 0.8043652, 0.82653236, 0.92003566, 0.6112387, 0.67438895, 0.6910336,
-0.79438055, 0.44455358, 0.13145985, 0.04016586, 0.26542372, 0.07187113, 0.21277027, 0.14576113, 0.77772665, 0.59611356,
-0.47446412, 0.6784915, 0.62820864, 0.62324655, 0.34820905, 0.094478644, 0.62985826, 0.30533785, 0.122310445, 0.84875596,
-0.22691421, 0.7269437, 0.40947318, 0.7116395, 0.039879926, 0.5329969, 0.44138008, 0.08615084, 0.39769763, 0.65121627,
-0.93361884, 0.52200013, 0.7655102, 0.60780525, 0.9355199, 0.21502401, 0.64518875, 0.45211464, 0.0770294, 0.6633778,
-0.5874192, 0.541437, 0.7165977, 0.7648834, 0.2311502, 0.3869329, 0.33478996, 0.915135, 0.82982254, 0.70988655,
-0.19667415, 0.6146979, 0.4889283, 0.825633, 0.46411943, 0.067436874, 0.035080392, 0.41982034, 0.0002859342, 0.7324268,
-0.630491, 0.12661943, 0.7480635, 0.12651038, 0.6624947, 0.952464, 0.9129812, 0.020403363, 0.6877267, 0.13318504,
-0.44928992, 0.1777436, 0.22830844, 0.45893264, 0.2613367, 0.68547726, 0.010346001, 0.6445898, 0.4804893, 0.652947,
-0.19820693, 0.52624506, 0.25632828, 0.687811, 0.4545421, 0.31892103, 0.033071853, 0.9398772, 0.14368583, 0.868083,
-0.17994362, 0.2253684, 0.4518287, 0.34460258, 0.032886766, 0.4607998, 0.7933734, 0.59008723, 0.10238874, 0.27868623,
-0.47395167, 0.3143866, 0.22740832, 0.6966375, 0.26059666, 0.018930554, 0.3863894, 0.029995646, 0.5642963, 0.7786422,
-0.05709087, 0.39049065, 0.939331, 0.3473389, 0.53421986, 0.10424597, 0.8702912, 0.060252476, 0.6719683, 0.34357366,
-0.9193921, 0.97310406, 0.8767175, 0.8196437, 0.9532414, 0.22392152, 0.7259149, 0.88370585, 0.42604586, 0.80053693,
-0.8921038, 0.42025873, 0.54220104, 0.2018031, 0.17899537, 0.8838203, 0.29883677, 0.5596908, 0.42721438, 0.43561155,
-0.9325316, 0.0030762074, 0.37558094, 0.36504367, 0.8109921, 0.78945297, 0.2860374, 0.10448979, 0.8103827, 0.9286408,
-0.59050864, 0.733121, 0.91811895, 0.75881505, 0.35929412, 0.50084764, 0.4376691, 0.40776464, 0.7433961, 0.036675144,
-0.29301566, 0.5026836, 0.6039498, 0.7637594, 0.8865383, 0.6368321, 0.8482896, 0.7375279, 0.16834354, 0.65039957,
-0.8054092, 0.31060037, 0.6330381, 0.23635677, 0.41104206, 0.9163159, 0.5975231, 0.51167387, 0.008651535, 0.16378845,
-0.93788415, 0.62142515, 0.07332315, 0.49740508, 0.21002825, 0.15898286, 0.5021398, 0.78338593, 0.842509, 0.67814773,
-0.44615123, 0.8910721, 0.81629467, 0.39053923, 0.14259589, 0.42984807, 0.39912644, 0.61182153, 0.47850534, 0.17416,
-0.94116336, 0.5485095, 0.93614626, 0.15998314, 0.12323159, 0.27990827, 0.10008287, 0.6817622, 0.34777302, 0.4429782,
-0.9033245, 0.92599523, 0.39911312, 0.57960767, 0.09879101, 0.6715905, 0.4293604, 0.1065447, 0.55373114, 0.72755545,
-0.13469236, 0.06490368, 0.89501894, 0.4901958, 0.20424834, 0.9143371, 0.4943057, 0.24249884, 0.093760885, 0.98119396,
-0.5171895, 0.98570156, 0.03316852, 0.83449155, 0.22262509, 0.38937467, 0.6852789, 0.91334003, 0.3741735, 0.93012,
-0.05889999, 0.8203776, 0.43561292, 0.3995308, 0.77482325, 0.52015597, 0.491959, 0.23668702, 0.29174823, 0.47100535,
-0.0004876647, 0.29258174, 0.058090426, 0.75094986, 0.039467655, 0.8762597, 0.65349054, 0.44595045, 0.9557348, 0.20889449,
-0.78560257, 0.857584, 0.5880013, 0.36657903, 0.9257887, 0.917623, 0.89282674, 0.56462157, 0.35698256, 0.70941633,
-0.9863116, 0.51602036, 0.7323712, 0.62361115, 0.6686555, 0.31431475, 0.62929076, 0.4954881, 0.71537256, 0.68409234,
-0.4223781, 0.2576187, 0.9507506, 0.6227555, 0.98070633, 0.22460775, 0.9276111, 0.28221866, 0.79502386, 0.34636542,
-0.73588413, 0.23932843, 0.95760524, 0.165279, 0.1445174, 0.20131597, 0.23237628, 0.069033906, 0.47374207, 0.85720026,
-0.62732923, 0.9273374, 0.8797045, 0.5823319, 0.48469374, 0.48446727, 0.5602105, 0.43447927, 0.08229436, 0.7251529,
-0.24696892, 0.15800244, 0.7305779, 0.27164242, 0.78651637, 0.52798384, 0.9068334, 0.9652458, 0.3858727, 0.701181,
-0.9900118, 0.61060804, 0.7695977, 0.010617126, 0.97353226, 0.74698323, 0.5584152, 0.56709224, 0.47909376, 0.46733952,
-0.08193848, 0.56025684, 0.021746036, 0.8581723, 0.056763105, 0.49504068, 0.37791422, 0.36841872, 0.13806179, 0.49623904,
-0.66439724, 0.49313185, 0.19992432, 0.06987098, 0.09939649, 0.5778817, 0.50875056, 0.6859628, 0.3787626, 0.6165335,
-0.29448256, 0.2671305, 0.6831612, 0.77256113, 0.86718845, 0.016721206, 0.1577397, 0.86908734, 0.60879964, 0.73771054,
-0.9260521, 0.9931183, 0.9553855, 0.6149548, 0.6432144, 0.6867121, 0.1362564, 0.8724056, 0.21487932, 0.2914757,
-0.15006965, 0.53841466, 0.827184, 0.88963366, 0.03678374, 0.49687997, 0.41068372, 0.69972676, 0.9112206, 0.39565054,
-0.23823264, 0.8724524, 0.18832962, 0.8625602, 0.17285694, 0.814808, 0.87709564, 0.24918492, 0.99098384, 0.0400419,
-0.337301, 0.50882685, 0.7596191, 0.4003513, 0.5701869, 0.67127895, 0.5377463, 0.58496946, 0.42665657, 0.4126844,
-0.4416253, 0.63634497, 0.47108346, 0.08728689, 0.4664639, 0.75606793, 0.4399465, 0.79352754, 0.7357774, 0.3703085,
-0.6060375, 0.45801297, 0.9578667, 0.2131491, 0.49947786, 0.05359975, 0.8047887, 0.092825316, 0.4420979, 0.82840645,
-0.80961645, 0.8870715, 0.88142174, 0.17483743, 0.95417476, 0.6412428, 0.7787956, 0.4268327, 0.31944674, 0.3655048,
-0.9591336, 0.82571423, 0.2730702, 0.49853623, 0.95402527, 0.6018877, 0.4013689, 0.10104273, 0.39609635, 0.41678905,
-0.37486148, 0.083568096, 0.5134075, 0.6206753, 0.43400443, 0.879288, 0.5509602, 0.54647, 0.9008734, 0.5165872,
-0.86649024, 0.44492102, 0.14287159, 0.59825015, 0.60306793, 0.5545538, 0.7549232, 0.29624605, 0.13311216, 0.8252211,
-0.97727233, 0.013113789, 0.4740808, 0.37027258, 0.41117483, 0.7803232, 0.18494278, 0.45933047, 0.25912383, 0.89759016,
-0.65223086, 0.70374596, 0.696729, 0.02530885, 0.45354494, 0.72604835, 0.37366393, 0.2607464, 0.740833, 0.07488672,
-0.09028263, 0.23232558, 0.5259593, 0.80285954, 0.49901456, 0.5142126, 0.6828427, 0.67482007, 0.8954683, 0.39947143,
-0.8469645, 0.10512285, 0.96793056, 0.5708752, 0.43951672, 0.3617477, 0.6094873, 0.14313498, 0.2095005, 0.6536812,
-0.69434524, 0.09162968, 0.28734615, 0.0032832306, 0.86435634, 0.1627443, 0.748192, 0.11756273, 0.14470519, 0.8770196,
-0.1808899, 0.49417683, 0.55541307, 0.05822544, 0.73493844, 0.7449467, 0.48715448, 0.67122126, 0.871258, 0.8969622,
-0.097480536, 0.5101227, 0.5638622, 0.8596524, 0.050625734, 0.547108, 0.7358154, 0.12585375, 0.5857921, 0.09179724,
-0.11656108, 0.23052894, 0.051245883, 0.08715177, 0.38054147, 0.99865294, 0.9449794, 0.52267605, 0.93850327, 0.33627024,
-0.7660206, 0.56527996, 0.5301148, 0.018448701, 0.21858154, 0.3527876, 0.5497098, 0.90970516, 0.8359368, 0.69457,
-0.8745932, 0.93826604, 0.27187696, 0.3125383, 0.5562007, 0.1842225, 0.5277675, 0.42769375, 0.9526575, 0.3172483,
-0.42692894, 0.6223383, 0.5317706, 0.05290796, 0.7604585, 0.95036095, 0.44293094, 0.46826127, 0.67768395, 0.7362855,
-0.7999673, 0.96447843, 0.732718, 0.53498775, 0.13094164, 0.5322006, 0.9800079, 0.5454135, 0.64107084, 0.6978381,
-0.9973982, 0.82611024, 0.28991696, 0.8912221, 0.21720403, 0.17829505, 0.95865196, 0.7387076, 0.5309511, 0.19631897,
-0.47088546, 0.5172857, 0.5700186, 0.6212549, 0.90934134, 0.14368229, 0.033509336, 0.4772069, 0.25799018, 0.26822057,
-0.9098567, 0.08144851, 0.23202117, 0.09965124, 0.8946027, 0.91011477, 0.20554802, 0.7368892, 0.18159665, 0.024000084,
-0.20421462, 0.982354, 0.7866229, 0.2548194, 0.31985012, 0.6008187, 0.33242133, 0.64054847, 0.8357039, 0.58216345,
-0.991709, 0.70422333, 0.93731016, 0.481365, 0.26540005, 0.2826816, 0.39445987, 0.1114631, 0.6256465, 0.9872593,
-0.49869126, 0.502801, 0.2874233, 0.37285027, 0.78798145, 0.9159497, 0.5940891, 0.19026573, 0.99661946, 0.30708927,
-0.972747, 0.22176278, 0.55711097, 0.50695103, 0.99210435, 0.48853147, 0.73066276, 0.31519917, 0.3014048, 0.30852264,
-0.81126094, 0.39296088, 0.641503, 0.6758267, 0.27651158, 0.20563333, 0.14413832, 0.7506562, 0.83425117, 0.6119211,
-0.5156549, 0.094084926, 0.111242734, 0.1943373, 0.52530885, 0.70141363, 0.6949307, 0.41377264, 0.46683794, 0.4039004,
-0.006729609, 0.14215559, 0.643929, 0.52861464, 0.6094164, 0.7699462, 0.1471124, 0.43035918, 0.4892606, 0.7768686,
-0.5520188, 0.07926069, 0.8100583, 0.31712383, 0.17599839, 0.105730385, 0.861298, 0.6115966, 0.096338674, 0.5823481,
-0.77181137, 0.8434329, 0.35601455, 0.38469836, 0.79143435, 0.8786621, 0.11052005, 0.36277366, 0.9816422, 0.29069075,
-0.7936008, 0.31689015, 0.84836125, 0.8975044, 0.30179304, 0.66910535, 0.7490319, 0.1128883, 0.06641029, 0.5065654,
-0.058520928, 0.71377915, 0.26139554, 0.057382602, 0.059902266, 0.4363942, 0.28402662, 0.7941189, 0.018338913, 0.41957843,
-0.84011555, 0.083334126, 0.31743395, 0.88448983, 0.632089, 0.16329671, 0.78614104, 0.2592306, 0.7371803, 0.7307543,
-0.65942615, 0.7843387, 0.448717, 0.19856988, 0.9832678, 0.23512867, 0.23089947, 0.9125539, 0.015330798, 0.50689304,
-0.3566985, 0.74840975, 0.5451863, 0.5897733, 0.5238272, 0.05803223, 0.5820373, 0.29863194, 0.3247961, 0.35504016,
-0.5946355, 0.31640115, 0.34443474, 0.56206375, 0.45057517, 0.71026665, 0.99945617, 0.9638714, 0.26541534, 0.13849631,
-0.8829643, 0.48980126, 0.375708, 0.33565596, 0.84713924, 0.2741822, 0.26506215, 0.06282568, 0.07411481, 0.8247736,
-0.20549475, 0.37147272, 0.7787881, 0.5114459, 0.06287994, 0.09170583, 0.53814787, 0.72766066, 0.36066267, 0.5740568,
-0.58125937, 0.4875091, 0.93443453, 0.38214013, 0.13611887, 0.343025, 0.439904, 0.88665324, 0.7479947, 0.27300113,
-0.23567249, 0.26702806, 0.64713854, 0.8768345, 0.62392867, 0.8668972, 0.37270173, 0.20953032, 0.74263406, 0.249645,
-0.79297006, 0.51921165, 0.22451714, 0.50002253, 0.14954542, 0.22316273, 0.53761303, 0.83298886, 0.4991838, 0.35886934,
-0.17211881, 0.2717955, 0.6032087, 0.6913585, 0.5572369, 0.3954552, 0.55536675, 0.9935679, 0.19953707, 0.5041142,
-0.83427817, 0.3784089, 0.314831, 0.80111367, 0.58910114, 0.93846667, 0.7243342, 0.90195364, 0.8875172, 0.19598271,
-0.7190041, 0.3286175, 0.9850266, 0.11101766, 0.78108674, 0.06204771, 0.26299196, 0.434412, 0.23259473, 0.9129562,
-0.805412, 0.6069152, 0.38746944, 0.38912535, 0.10088234, 0.96387696, 0.6638193, 0.95578, 0.31959754, 0.22847345,
-0.3115305, 0.37913388, 0.009993258, 0.23851983, 0.4153668, 0.41456118, 0.20438069, 0.42340347, 0.9109214, 0.21107873,
-0.49882856, 0.6356594, 0.94547164, 0.3032011, 0.6398653, 0.84350127, 0.28676888, 0.49219108, 0.91027176, 0.49518922,
-0.13246326, 0.120954745, 0.76097316, 0.28658092, 0.6987022, 0.22736304, 0.99093944, 0.9257056, 0.7002313, 0.6252242,
-0.27464733, 0.76855415, 0.5823561, 0.6590438, 0.8844522, 0.3398702, 0.31862426, 0.7465068, 0.6956509, 0.36652556,
-0.857667, 0.8395885, 0.5234906, 0.021515984, 0.4141276, 0.16975257, 0.66144353, 0.084268354, 0.74926007, 0.25738105,
-0.67710805, 0.17162827, 0.045508236, 0.8244083, 0.0960102, 0.19057575, 0.6181607, 0.72341233, 0.5398176, 0.18800376,
-0.4236217, 0.27867505, 0.7231721, 0.28569725, 0.9364314, 0.73027444, 0.05330333, 0.28642786, 0.4187489, 0.29999506,
-0.524877, 0.5402621, 0.7965402, 0.54374623, 0.6375222, 0.29287475, 0.59746414, 0.73945713, 0.87245333, 0.5289497,
-0.56591946, 0.9066711, 0.17644554, 0.4428503, 0.94811606, 0.10301907, 0.7230459, 0.75794774, 0.5630336, 0.69387645,
-0.7217095, 0.5952119, 0.20668921, 0.5076471, 0.9429038, 0.57899195, 0.116416365, 0.23779334, 0.08508458, 0.6838532,
-0.11644924, 0.3750157, 0.6655195, 0.44926503, 0.73250407, 0.13684598, 0.37508807, 0.50176203, 0.1868861, 0.80313545,
-0.59311163, 0.8787036, 0.850959, 0.0108679095, 0.62208426, 0.5169506, 0.10222952, 0.28032187, 0.3375812, 0.83341235,
-0.0072284974, 0.2953556, 0.7233943, 0.7248724, 0.5782856, 0.9296651, 0.3335729, 0.28889313, 0.6008424, 0.05853025,
-0.17645839, 0.3596708, 0.6543726, 0.18860014, 0.41250044, 0.19090378, 0.24115163, 0.7271805, 0.7103462, 0.8112701,
-0.727931, 0.22128391, 0.5710617, 0.7598981, 0.10076484, 0.8430059, 0.7442529, 0.1958213, 0.8855628, 0.4259532,
-0.47676244, 0.8360945, 0.90021217, 0.25167224, 0.67662466, 0.8210937, 0.6516214, 0.940647, 0.8709795, 0.802839,
-0.8032731, 0.08619493, 0.9009196, 0.12835586, 0.62667704, 0.2334408, 0.224331, 0.6623589, 0.59836745, 0.4311805,
-0.27579898, 0.37504902, 0.5699756, 0.5263111, 0.10548131, 0.7859446, 0.72429395, 0.96349615, 0.6241076, 0.7352797,
-0.18541217, 0.13775158, 0.40333033, 0.17488916, 0.5817678, 0.34036386, 0.45945865, 0.40270033, 0.51197547, 0.59140676,
-0.5392824, 0.3005046, 0.85620105, 0.9075073, 0.007996995, 0.6417361, 0.3203643, 0.44270578, 0.13322107, 0.86732405,
-0.6186749, 0.08189404, 0.59745383, 0.4543823, 0.15015423, 0.10171343, 0.2661189, 0.37390104, 0.14619094, 0.8906801,
-0.096799746, 0.68812525, 0.31653944, 0.13569976, 0.6174268, 0.6655215, 0.6828646, 0.72603047, 0.54658806, 0.28631318,
-0.77398217, 0.8216307, 0.15038341, 0.0069607063, 0.8918981, 0.97529435, 0.518848, 0.6624684, 0.5183141, 0.46374524,
-0.4655803, 0.28158814, 0.83027506, 0.75678355, 0.11660483, 0.10351813, 0.54029775, 0.948948, 0.024734931, 0.48005438,
-0.074244976, 0.0855576, 0.2565094, 0.62129533, 0.49460703, 0.85115707, 0.98396516, 0.7205013, 0.2900805, 0.34247547,
-0.9588715, 0.5943338, 0.89611775, 0.8469079, 0.09334188, 0.79704416, 0.9315106, 0.59049314, 0.5624842, 0.17485987,
-0.5828654, 0.60365057, 0.85558695, 0.6824457, 0.4250998, 0.8152116, 0.8578502, 0.55975586, 0.01909494, 0.5139087,
-0.12522376, 0.73391664, 0.7012955, 0.06653367, 0.2120682, 0.6884245, 0.5651213, 0.5290881, 0.51235366, 0.040741026,
-0.9913292, 0.7983467, 0.3723879, 0.17583862, 0.50487375, 0.87124646, 0.3854704, 0.9833672, 0.66344166, 0.31956065,
-0.1720075, 0.94980466, 0.38646382, 0.8498751, 0.89718896, 0.4705944, 0.22997065, 0.57406366, 0.19619557, 0.67939544,
-0.9933069, 0.4242093, 0.70140636, 0.7761718, 0.21725173, 0.22495484, 0.89303833, 0.82958406, 0.6348397, 0.40491733,
-0.23192288, 0.40242258, 0.07813944, 0.5217432, 0.18353066, 0.7845187, 0.23126268, 0.6797483, 0.17757194, 0.55385333,
-0.42974123, 0.874483, 0.8963142, 0.6995343, 0.34190118, 0.17541912, 0.34745282, 0.85142046, 0.16934472, 0.7414738,
-0.4584539, 0.99105763, 0.33289248, 0.8329583, 0.04743413, 0.5671199, 0.09694037, 0.5962161, 0.9585869, 0.2799189,
-0.9782081, 0.5558863, 0.3485275, 0.25852436, 0.08763776, 0.76958495, 0.8716652, 0.86472064, 0.6663444, 0.1126702,
-0.23933174, 0.55022234, 0.39649174, 0.64234227, 0.24965419, 0.118823886, 0.5278951, 0.0018720366, 0.43427062, 0.04183261,
-0.877502, 0.04161787, 0.66023934, 0.8933659, 0.9464634, 0.24086526, 0.069530085, 0.24518117, 0.47430903, 0.61641073,
-0.6875784, 0.6350466, 0.7211614, 0.89765304, 0.5756452, 0.87385494, 0.5259555, 0.63778985, 0.6118965, 0.5723162,
-0.3037539, 0.48273215, 0.18507604, 0.05667453, 0.5021421, 0.90823156, 0.59456587, 0.69055027, 0.5833041, 0.92861027,
-0.039224792, 0.095068336, 0.16194543, 0.9167543, 0.40241688, 0.93659025, 0.895647, 0.4551616, 0.31206095, 0.8467725,
-0.7000548, 0.62648404, 0.39041162, 0.049933646, 0.42509183, 0.6042851, 0.8290609, 0.49883872, 0.06669706, 0.37579927,
-0.5928684, 0.89010525, 0.3899755, 0.8619544, 0.7380787, 0.39476988, 0.8565418, 0.6035648, 0.39122385, 0.038231853,
-0.64629936, 0.37897983, 0.6618771, 0.54569876, 0.577186, 0.59251004, 0.47310117, 0.8044071, 0.49523613, 0.6390549,
-0.97820795, 0.07079393, 0.3257289, 0.765124, 0.8722614, 0.6772699, 0.092320524, 0.1351424, 0.6315827, 0.89785695,
-0.07917066, 0.09572715, 0.6238532, 0.20750481, 0.33574188, 0.14911953, 0.70509285, 0.29999104, 0.1786756, 0.0076469877,
-0.08004845, 0.29208216, 0.063937746, 0.27382907, 0.20047311, 0.32107502, 0.96460694, 0.84471285, 0.47274768, 0.8325818,
-0.13118395, 0.024653764, 0.0036025788, 0.42764217, 0.39759132, 0.52207446, 0.56437635, 0.62485147, 0.989693, 0.060808785,
-0.30244938, 0.7213994, 0.9719821, 0.49336693, 0.9590612, 0.5505722, 0.75512666, 0.4543723, 0.2099569, 0.42806646,
-0.8874172, 0.17311013, 0.6257315, 0.48758915, 0.55900645, 0.68612576, 0.0068561803, 0.051899806, 0.56465095, 0.5511864,
-0.71266294, 0.2476077, 0.6623947, 0.7990009, 0.76667297, 0.054516893, 0.092124574, 0.19621104, 0.80991346, 0.8136675,
-0.58474314, 0.08024137, 0.31029803, 0.117866814, 0.70519763, 0.35864902, 0.32010004, 0.5705708, 0.3147679, 0.64990085,
-0.56594837, 0.51023465, 0.6347559, 0.044681232, 0.94516456, 0.9580738, 0.39892223, 0.51601344, 0.8686357, 0.71146554,
-0.51521826, 0.51247656, 0.06020054, 0.43850663, 0.3481458, 0.054841675, 0.059004717, 0.1729812, 0.7266939, 0.9045443,
-0.45844766, 0.5589156, 0.6444588, 0.39628944, 0.8433233, 0.8071758, 0.8628121, 0.5078647, 0.78239155, 0.20035744,
-0.36602575, 0.43628535, 0.7371319, 0.91475004, 0.985238, 0.20242831, 0.61285174, 0.6177135, 0.8538363, 0.8085992,
-0.65559465, 0.57611114, 0.32757533, 0.09844793, 0.2984492, 0.07226656, 0.020040827, 0.87179136, 0.769721, 0.65035594,
-0.2996443, 0.14711884, 0.8438769, 0.4102236, 0.1914532, 0.007032739, 0.8657759, 0.23846649, 0.20135792, 0.13798875,
-0.09526171, 0.8910575, 0.7336219, 0.6682783, 0.34543982, 0.078932896, 0.77534467, 0.14545049, 0.45326862, 0.14571752,
-0.44198993, 0.44129124, 0.31914487, 0.9180948, 0.24894963, 0.8823365, 0.23134027, 0.54601085, 0.09784024, 0.7710568,
-0.787135, 0.99102074, 0.73814374, 0.13203558, 0.90071315, 0.2189069, 0.5924085, 0.32690832, 0.7232968, 0.97820526,
-0.33665246, 0.37438527, 0.41635555, 0.71584755, 0.7133375, 0.76453716, 0.84248924, 0.6592971, 0.7530081, 0.2195163,
-0.29692188, 0.87459034, 0.41852275, 0.62400347, 0.20836602, 0.8583531, 0.82797396, 0.9257821, 0.16127396, 0.3091167,
-0.77569246, 0.31976497, 0.14062625, 0.43030116, 0.35085374, 0.104240976, 0.15291376, 0.6015863, 0.76756513, 0.12653293,
-0.48652443, 0.44843635, 0.42215365, 0.47506335, 0.80906504, 0.06760467, 0.02493567, 0.6032973, 0.20475733, 0.48441246,
-0.039847255, 0.5720432, 0.7930028, 0.8783239, 0.47413486, 0.91254467, 0.57249796, 0.11414025, 0.9236696, 0.042360075,
-0.39093295, 0.6666264, 0.16563436, 0.41418016, 0.20251282, 0.016887465, 0.23375902, 0.9860544, 0.36499384, 0.60909647,
-0.6116234, 0.24090295, 0.891732, 0.6264752, 0.7329919, 0.8484855, 0.45243672, 0.9434594, 0.8149384, 0.14076136,
-0.8334174, 0.22467664, 0.72102475, 0.6768615, 0.26926944, 0.20364925, 0.52676225, 0.2623023, 0.95616627, 0.43830907,
-0.531743, 0.03877351, 0.67791677, 0.72520506, 0.7356, 0.81989807, 0.282802, 0.007973485, 0.27255052, 0.7921776,
-0.8338457, 0.038881265, 0.23830348, 0.59566087, 0.872789, 0.7989443, 0.68031126, 0.16652757, 0.14533207, 0.62564933,
-0.46010798, 0.6290386, 0.29920182, 0.7829082, 0.20894268, 0.16625631, 0.94560164, 0.48877287, 0.14491072, 0.9988636,
-0.49012524, 0.9714567, 0.029888112, 0.92668474, 0.07735347, 0.5728499, 0.5629862, 0.16652691, 0.8908752, 0.91309386,
-0.56568354, 0.44446322, 0.67090887, 0.022760825, 0.3069157, 0.7945361, 0.9863731, 0.12536389, 0.80407244, 0.47032514,
-0.523338, 0.36023465, 0.11697024, 0.33051696, 0.9782011, 0.9027044, 0.7395717, 0.89500856, 0.51626235, 0.5693437,
-0.8742964, 0.7940291, 0.86306274, 0.27368698, 0.30205235, 0.86238897, 0.008993154, 0.31161872, 0.5183074, 0.29993913,
-0.2359581, 0.51378435, 0.27565238, 0.23223823, 0.059965752, 0.01564475, 0.9581297, 0.276441, 0.4759925, 0.41440654,
-0.17988315, 0.82023776, 0.68470037, 0.6745856, 0.47552556, 0.12989059, 0.85448647, 0.69937116, 0.94848365, 0.17464903,
-0.83327824, 0.6679777, 0.65026456, 0.32153153, 0.038797423, 0.7716544, 0.58140045, 0.3972219, 0.7207085, 0.44452676,
-0.78554296, 0.67475444, 0.6070565, 0.50413334, 0.23436703, 0.009553685, 0.08458229, 0.884732, 0.27055123, 0.96255636,
-0.9445748, 0.46313068, 0.41901603, 0.10185582, 0.38946053, 0.05405868, 0.10932874, 0.18847717, 0.79816145, 0.17216177,
-0.007902476, 0.30962202, 0.36313507, 0.34365836, 0.46666092, 0.5679804, 0.8635198, 0.9541208, 0.19344081, 0.2883113,
-0.4342443, 0.5609078, 0.55573255, 0.03146575, 0.6288636, 0.50512874, 0.21318124, 0.18056706, 0.44021857, 0.46597186,
-0.045308296, 0.96975446, 0.42881992, 0.9859273, 0.23007429, 0.37014756, 0.24896163, 0.54840875, 0.932071, 0.98473877,
-0.6623257, 0.39292327, 0.5990605, 0.5485467, 0.4366243, 0.47592095, 0.31161934, 0.26339814, 0.037472416, 0.6663866,
-0.1460339, 0.13046144, 0.6912912, 0.9822399, 0.528312, 0.38366696, 0.90739816, 0.3875503, 0.47299224, 0.88433176,
-0.8408774, 0.92876166, 0.7482586, 0.33218956, 0.12685347, 0.038148023, 0.8808021, 0.37720776, 0.11358407, 0.09651337,
-0.3190188, 0.31511107, 0.022049852, 0.20870206, 0.6259856, 0.041321024, 0.9618473, 0.007185834, 0.5948415, 0.15294261,
-0.19350938, 0.9497831, 0.14309464, 0.77383196, 0.31993797, 0.91484684, 0.27846324, 0.44658, 0.45761526, 0.8464073,
-0.46274942, 0.86141133, 0.075416476, 0.0477392, 0.14386131, 0.733564, 0.64466465, 0.26687092, 0.42169324, 0.39847627,
-0.5951189, 0.9344116, 0.14981407, 0.94095904, 0.3473678, 0.83092284, 0.108411595, 0.48258916, 0.3562543, 0.48699102,
-0.42181966, 0.9002123, 0.7927088, 0.32004964, 0.6908224, 0.8910943, 0.78566706, 0.9744266, 0.012251603, 0.21200661,
-0.7596848, 0.4342221, 0.9195925, 0.26717675, 0.63376397, 0.45760745, 0.2396946, 0.97431064, 0.06484076, 0.8924216,
-0.39665636, 0.6949764, 0.5854926, 0.1963652, 0.5578238, 0.2590978, 0.799969, 0.2021356, 0.42646417, 0.48901513,
-0.8064353, 0.7958741, 0.0903257, 0.9706242, 0.42458767, 0.56253713, 0.068702534, 0.75536686, 0.3569168, 0.25276697,
-0.94789696, 0.670238, 0.2546193, 0.2096866, 0.6387915, 0.16089676, 0.01481907, 0.8826373, 0.3071951, 0.8897603,
-0.59122825, 0.13410094, 0.4177484, 0.4638327, 0.09033466, 0.72684324, 0.3147197, 0.5963436, 0.76222587, 0.43172458,
-0.091125324, 0.58353144, 0.5479625, 0.52323645, 0.40557137, 0.9638107, 0.3438964, 0.9489683, 0.8425891, 0.07122685,
-0.38890493, 0.48432773, 0.61739385, 0.8120738, 0.9445246, 0.7264184, 0.4403571, 0.375806, 0.55757374, 0.396927,
-0.24427874, 0.9173317, 0.8949405, 0.5367038, 0.8977869, 0.6723343, 0.3781257, 0.626493, 0.88028955, 0.6977444,
-0.24781741, 0.4723589, 0.993141, 0.9251922, 0.16164163, 0.36436552, 0.12227554, 0.73138285, 0.80411524, 0.6749808,
-0.8170004, 0.06585078, 0.040048227, 0.23596825, 0.5008554, 0.10690048, 0.51670706, 0.6056746, 0.5193081, 0.3639163,
-0.28648618, 0.9389137, 0.03876988, 0.36529887, 0.18744585, 0.17379361, 0.68859094, 0.011258623, 0.62544954, 0.733237,
-0.585685, 0.7174034, 0.06867873, 0.14484468, 0.82340944, 0.916546, 0.49118677, 0.6922017, 0.65043217, 0.58015907,
-0.60414284, 0.70897424, 0.57169074, 0.8825929, 0.5799266, 0.17842796, 0.8772835, 0.65897226, 0.03584844, 0.7908864,
-0.15562724, 0.7724511, 0.10718488, 0.5163733, 0.41125825, 0.3089037, 0.43358904, 0.62784207, 0.73774636, 0.98784804,
-0.6757746, 0.111016914, 0.10593328, 0.07087821, 0.08929581, 0.09959695, 0.99717206, 0.89520353, 0.4125588, 0.5843094,
-0.6157137, 0.82450545, 0.95524246, 0.939149, 0.7597735, 0.5775119, 0.36722296, 0.15617695, 0.78537226, 0.009017896,
-0.29651013, 0.029618707, 0.97541016, 0.83456314, 0.5776098, 0.8132339, 0.6102185, 0.55230546, 0.73358643, 0.51450574,
-0.48295695, 0.86334467, 0.9544553, 0.6625841, 0.90438455, 0.49312592, 0.603041, 0.50081253, 0.7932971, 0.4803297,
-0.1812559, 0.9820799, 0.24641345, 0.45153904, 0.1751727, 0.3311218, 0.81720865, 0.16803588, 0.7565998, 0.8337463,
-0.9416807, 0.2774121, 0.8424698, 0.7287285, 0.6913379, 0.64615583, 0.13560674, 0.27137014, 0.4932684, 0.27606192,
-0.48937842, 0.4448666, 0.16161712, 0.89805305, 0.10135246, 0.75236905, 0.87005013, 0.29265827, 0.034764472, 0.26664755,
-0.9744709, 0.86641043, 0.3628798, 0.30504256, 0.827762, 0.31443018, 0.7832053, 0.5238711, 0.65939045, 0.246488,
-0.9960252, 0.44218266, 0.7957057, 0.8998401, 0.572825, 0.20554484, 0.020874852, 0.22572684, 0.97124624, 0.2582287,
-0.35751918, 0.33167085, 0.007544129, 0.5172352, 0.99095124, 0.73638934, 0.8204628, 0.34836042, 0.3501866, 0.4228037,
-0.46107167, 0.5245504, 0.1332714, 0.48995224, 0.8592754, 0.07527029, 0.91453224, 0.53742725, 0.90096647, 0.3769077,
-0.8629506, 0.6117356, 0.61197966, 0.2467804, 0.2800367, 0.047195755, 0.6491609, 0.261777, 0.32522804, 0.8958076,
-0.7314942, 0.6443233, 0.32141203, 0.7765358, 0.90912837, 0.6428001, 0.85886633, 0.8456446, 0.31409132, 0.09137268,
-0.49396735, 0.43484485, 0.17368458, 0.23658675, 0.78541636, 0.47147486, 0.30891126, 0.30575344, 0.040564716, 0.49755472,
-0.2910126, 0.48344758, 0.32476038, 0.59433854, 0.39527807, 0.7457836, 0.71969116, 0.76076376, 0.23719852, 0.9437555,
-0.087228395, 0.55868584, 0.023132376, 0.45437896, 0.6913095, 0.8167484, 0.20313835, 0.35673562, 0.58082384, 0.2164753,
-0.21640398, 0.06888765, 0.22333595, 0.8095938, 0.88294035, 0.42810574, 0.43805102, 0.37539294, 0.46136406, 0.80856186,
-0.7382845, 0.34340748, 0.2212123, 0.8276733, 0.60479504, 0.24804658, 0.3195629, 0.7270735, 0.3812577, 0.16334477,
-0.92310894, 0.09810257, 0.6084461, 0.37033582, 0.004144284, 0.9352815, 0.41171247, 0.71930563, 0.54527724, 0.968668,
-0.2683365, 0.9521756, 0.7249296, 0.8240894, 0.28115076, 0.22212493, 0.26011166, 0.5151666, 0.71139824, 0.9671723,
-0.3077326, 0.3442982, 0.29939967, 0.42863667, 0.20547101, 0.7438209, 0.33747354, 0.19545908, 0.8495839, 0.44326293,
-0.49718547, 0.4760649, 0.97547793, 0.4174791, 0.29336637, 0.11830141, 0.46044156, 0.85300016, 0.8054495, 0.9476588,
-0.016393282, 0.7187454, 0.8301157, 0.49269608, 0.5402253, 0.78610885, 0.6184779, 0.39712286, 0.54652256, 0.3826701,
-0.98793495, 0.80439633, 0.015675247, 0.4140854, 0.85561216, 0.5788107, 0.7987029, 0.17980942, 0.16486481, 0.26032335,
-0.597808, 0.2162534, 0.86972165, 0.102014296, 0.47148252, 0.7922716, 0.97669774, 0.3074505, 0.53072304, 0.16284934,
-0.7616834, 0.40711153, 0.7097171, 0.7637394, 0.950779, 0.58898723, 0.5141825, 0.8067036, 0.88841134, 0.41936216,
-0.12534304, 0.94035065, 0.6489365, 0.46691382, 0.45532802, 0.69278914, 0.46038964, 0.56139255, 0.56186694, 0.7145557,
-0.31959853, 0.28063214, 0.6881353, 0.54512614, 0.3498508, 0.8001399, 0.8490237, 0.7281014, 0.021213572, 0.7479538,
-0.8094111, 0.31102738, 0.8663998, 0.38367322, 0.6209867, 0.5808234, 0.09467922, 0.25193584, 0.46330634, 0.26662496,
-0.06462818, 0.99199927, 0.29139808, 0.74550265, 0.13498032, 0.65745735, 0.5673169, 0.40280786, 0.64668626, 0.7786934,
-0.33188194, 0.4153052, 0.7455836, 0.8161674, 0.8432508, 0.48105124, 0.7189762, 0.16459095, 0.41388863, 0.15063916,
-0.73996353, 0.78608114, 0.78549004, 0.14045759, 0.609951, 0.8143157, 0.07395084, 0.26526332, 0.8459271, 0.8745046,
-0.5981099, 0.20845382, 0.098086186, 0.29524195, 0.6499275, 0.32759923, 0.98923403, 0.9426327, 0.41014582, 0.6923934,
-0.23282301, 0.44621587, 0.08141512, 0.24252021, 0.4160718, 0.3941059, 0.5654438, 0.050232418, 0.5404224, 0.13993548,
-0.8618472, 0.9300883, 0.8380472, 0.31266716, 0.52666146, 0.27854705, 0.20650926, 0.1509405, 0.13555165, 0.32066464,
-0.5835065, 0.30205357, 0.5568808, 0.7721817, 0.18058343, 0.123428136, 0.31721902, 0.45034164, 0.16623993, 0.5156516,
-0.4918172, 0.7763435, 0.75444514, 0.7214952, 0.91781616, 0.29374766, 0.704666, 0.5429698, 0.7243858, 0.21584511,
-0.24887188, 0.02371842, 0.7248409, 0.7059916, 0.012657363, 0.6680217, 0.37040663, 0.785419, 0.7685805, 0.37138042,
-0.12108998, 0.83829355, 0.80708104, 0.08948117, 0.108886935, 0.93076944, 0.8893351, 0.30923343, 0.061936773, 0.29264367,
-0.07688689, 0.11510216, 0.8839925, 0.02477082, 0.64811826, 0.08550372, 0.17564313, 0.11655201, 0.39485103, 0.23291379,
-0.57388103, 0.6635394, 0.42655468, 0.9197065, 0.071792774, 0.5597881, 0.57721263, 0.8508891, 0.75952435, 0.5125618,
-0.75302154, 0.53180003, 0.6817611, 0.79485947, 0.3945616, 0.6535236, 0.9692625, 0.66496396, 0.61260825, 0.98704666,
-0.40441254, 0.3954326, 0.48103306, 0.43174213, 0.13895822, 0.13376972, 0.13972592, 0.7000701, 0.05787335, 0.92715365,
-0.49237853, 0.2538546, 0.390568, 0.5356667, 0.7974994, 0.45755056, 0.41173887, 0.8873745, 0.017688395, 0.54909885,
-0.3535568, 0.038445998, 0.54970914, 0.549375, 0.5396221, 0.54508686, 0.43334106, 0.089132994, 0.6302092, 0.99459463,
-0.11624123, 0.5106792, 0.50394374, 0.40780434, 0.8285013, 0.17844845, 0.18250638, 0.99481255, 0.7807483, 0.93802303,
-0.42006215, 0.87714255, 0.7930158, 0.8323707, 0.020183232, 0.4991669, 0.14123203, 0.1460944, 0.9973601, 0.93701106,
-0.24178477, 0.081888, 0.64727557, 0.06350941, 0.6334899, 0.36596653, 0.84572345, 0.931658, 0.89212, 0.59387136,
-0.70042866, 0.050592937, 0.06986087, 0.063278705, 0.81091243, 0.98169935, 0.74991083, 0.98276365, 0.7071655, 0.6190509,
-0.27504414, 0.41692632, 0.106626175, 0.07966534, 0.12903668, 0.47641423, 0.24543023, 0.71733844, 0.5291918, 0.040455237,
-0.40385485, 0.28724664, 0.091772884, 0.69319814, 0.7528099, 0.034353238, 0.8634036, 0.44043434, 0.77431446, 0.46253473,
-0.332725, 0.25084835, 0.10269255, 0.18687698, 0.23759438, 0.36946923, 0.8072817, 0.72973704, 0.021458272, 0.038483858,
-0.7492561, 0.1584684, 0.43892893, 0.37830916, 0.6619669, 0.8248584, 0.9752618, 0.5676102, 0.93447274, 0.15707563,
-0.120536305, 0.12838502, 0.40246627, 0.8516648, 0.19001648, 0.41318202, 0.95882004, 0.3766627, 0.31046882, 0.7765592,
-0.11829578, 0.3094765, 0.20844917, 0.24463072, 0.28632593, 0.024195805, 0.31423378, 0.9197492, 0.84207094, 0.75956744,
-0.66913253, 0.5156932, 0.6958802, 0.4907079, 0.29119918, 0.24538647, 0.8483177, 0.7134637, 0.031231258, 0.92795146,
-0.059091415, 0.29579335, 0.5059616, 0.6172388, 0.34199843, 0.20433997, 0.84838206, 0.2510278, 0.9968605, 0.82441235,
-0.41064918, 0.43061897, 0.41926822, 0.2448991, 0.92018807, 0.43977955, 0.95001924, 0.19429821, 0.09198324, 0.63777107,
-0.51062465, 0.055512622, 0.72553927, 0.17490527, 0.48794308, 0.60484314, 0.43250486, 0.91175836, 0.5604656, 0.94463,
-0.56486434, 0.24535634, 0.34543145, 0.38251737, 0.7174677, 0.82250243, 0.8035149, 0.59121037, 0.9026323, 0.081985965,
-0.17581372, 0.06320599, 0.9228887, 0.017658591, 0.3489183, 0.23851357, 0.096424945, 0.45098105, 0.57051986, 0.8514196,
-0.29536724, 0.6540195, 0.62148046, 0.39346015, 0.41732678, 0.0035787956, 0.5702541, 0.33105636, 0.12929575, 0.7371553,
-0.7718351, 0.93662375, 0.6905622, 0.052230474, 0.25954804, 0.16529284, 0.08518753, 0.03675085, 0.52743137, 0.097685665,
-0.6362647, 0.35880888, 0.2916659, 0.009997273, 0.46195737, 0.4474187, 0.13262391, 0.7078807, 0.825987, 0.24942951,
-0.5084182, 0.9815238, 0.3412385, 0.70904595, 0.6492628, 0.9108448, 0.62387586, 0.9519713, 0.9651906, 0.71388894,
-0.25224832, 0.4724585, 0.4619146, 0.16547702, 0.31015086, 0.23919, 0.37264377, 0.8706582, 0.7581105, 0.18362544,
-0.15332605, 0.05967409, 0.9235497, 0.47283417, 0.21515496, 0.93655837, 0.3623536, 0.6114832, 0.93150276, 0.9699081,
-0.8709549, 0.8623734, 0.5050694, 0.87986624, 0.2287371, 0.7903113, 0.5953852, 0.98151624, 0.40296772, 0.34870324,
-0.541417, 0.13321623, 0.07156025, 0.81354237, 0.84543735, 0.16380614, 0.8968943, 0.12618889, 0.6998464, 0.22276738,
-0.07477489, 0.2619657, 0.94977015, 0.6423615, 0.09610346, 0.4487441, 0.05797409, 0.8684043, 0.49389097, 0.7127044,
-0.54849124, 0.012392659, 0.020468513, 0.99528253, 0.8429341, 0.3898749, 0.96738917, 0.58204836, 0.9367399, 0.5198395,
-0.6438048, 0.39112753, 0.46769053, 0.40940732, 0.64220846, 0.02010981, 0.9881138, 0.11000732, 0.6273968, 0.051348828,
-0.039664086, 0.2361647, 0.91163677, 0.7087354, 0.8951332, 0.6089892, 0.91260326, 0.86270785, 0.7837628, 0.779993,
-0.73233724, 0.72698087, 0.48762527, 0.69026333, 0.800212, 0.5290243, 0.11274772, 0.07627774, 0.9706083, 0.45556244,
-0.19641699, 0.31484595, 0.18944897, 0.18000686, 0.5789626, 0.6836474, 0.79427516, 0.54036283, 0.00015307916, 0.07599365,
-0.46063024, 0.94796675, 0.24100749, 0.44254217, 0.67304033, 0.31232652, 0.10075587, 0.31173313, 0.100149296, 0.23394488,
-0.47727165, 0.10468131, 0.79828554, 0.1567469, 0.78750235, 0.9168239, 0.9035022, 0.7774272, 0.6091953, 0.11318414,
-0.9073621, 0.9118361, 0.139399, 0.17183441, 0.85493183, 0.7248181, 0.04671574, 0.7316299, 0.1297728, 0.21148583,
-0.814714, 0.37224042, 0.8625547, 0.70776916, 0.31936276, 0.7843705, 0.4859734, 0.04508312, 0.017223012, 0.4878855,
-0.42826846, 0.8010146, 0.97612846, 0.73666346, 0.9782908, 0.09173568, 0.51656044, 0.032702066, 0.3925045, 0.6621387,
-0.7801451, 0.01684795, 0.93116754, 0.886969, 0.16863157, 0.54879415, 0.80856776, 0.06917309, 0.5876103, 0.94822216,
-0.26561078, 0.36912593, 0.18196031, 0.8886635, 0.41923082, 0.1050312, 0.24212655, 0.09051639, 0.8373841, 0.0031318855,
-0.4308505, 0.8584191, 0.7602042, 0.121309794, 0.68491566, 0.10634747, 0.9357077, 0.4027356, 0.19354361, 0.7631962,
-0.2082577, 0.014013676, 0.3391254, 0.46763408, 0.43134072, 0.7978661, 0.44107288, 0.9755858, 0.5391376, 0.7705686,
-0.9758027, 0.4168003, 0.4574728, 0.06900084, 0.22227472, 0.059142508, 0.6190543, 0.08746498, 0.3174326, 0.8732596,
-0.84960914, 0.42604402, 0.19531794, 0.38937265, 0.2312882, 0.921726, 0.25664374, 0.8098577, 0.20205325, 0.06228409,
-0.61308646, 0.40583217, 0.8756295, 0.8244142, 0.7399645, 0.2515971, 0.030000538, 0.7143262, 0.45732272, 0.6213647,
-0.6639583, 0.26654074, 0.5513788, 0.0668155, 0.02732918, 0.014050223, 0.40094635, 0.69120336, 0.8990351, 0.6257732,
-0.48729318, 0.8482427, 0.08530297, 0.320284, 0.91358703, 0.7822137, 0.8186957, 0.94975275, 0.2363459, 0.50961477,
-0.54122233, 0.63121516, 0.77353257, 0.4768535, 0.15748215, 0.56997055, 0.54117084, 0.6330586, 0.32903638, 0.9706776,
-0.02914197, 0.90472806, 0.6301423, 0.69606787, 0.20930128, 0.5830684, 0.8746652, 0.12850243, 0.36204344, 0.21723796,
-0.5207796, 0.5654404, 0.9108227, 0.57628006, 0.5749909, 0.7648438, 0.3205292, 0.5553455, 0.91082716, 0.9577508,
-0.43290135, 0.08024777, 0.47798032, 0.94770795, 0.0801424, 0.03274318, 0.49300817, 0.07452531, 0.90933335, 0.45735866,
-0.4728794, 0.7678877, 0.362167, 0.9283575, 0.5966312, 0.5825651, 0.21810043, 0.3892351, 0.11098274, 0.33051863,
-0.9075484, 0.6901933, 0.5877093, 0.019107932, 0.9888351, 0.9757819, 0.72039247, 0.19725248, 0.90186256, 0.39263836,
-0.24944134, 0.98582536, 0.72223145, 0.3712856, 0.5377763, 0.9488942, 0.42674774, 0.68243426, 0.6159255, 0.1765581,
-0.09006023, 0.8001399, 0.21916907, 0.9046848, 0.74435854, 0.7528919, 0.20327342, 0.9824652, 0.9796489, 0.9924258,
-0.5467434, 0.9312941, 0.44436273, 0.58030856, 0.05020233, 0.742708, 0.49253845, 0.4588724, 0.95887285, 0.10436046,
-0.31235072, 0.29575568, 0.17266272, 0.516695, 0.20791732, 0.48705408, 0.045656245, 0.9908814, 0.3905812, 0.647737,
-0.15581739, 0.5356661, 0.77330965, 0.93442464, 0.2404584, 0.10740854, 0.47102425, 0.6830245, 0.27474937, 0.2359432,
-0.7725085, 0.73792726, 0.21760361, 0.9094368, 0.845895, 0.31814724, 0.5414626, 0.14192294, 0.32108325, 0.7950682,
-0.45635575, 0.96787536, 0.72356147, 0.511565, 0.8642074, 0.79430455, 0.62747717, 0.70247406, 0.6967675, 0.2573045,
-0.7072357, 0.212392, 0.591884, 0.33191186, 0.8366084, 0.01107724, 0.15798447, 0.5099381, 0.33985013, 0.9427938,
-0.27168378, 0.8095139, 0.18412302, 0.72292966, 0.33185193, 0.5744235, 0.078152075, 0.2632259, 0.67080003, 0.8897701,
-0.94559145, 0.9037333, 0.66979814, 0.595513, 0.19138126, 0.18794204, 0.8121047, 0.26174462, 0.07021725, 0.44615385,
-0.47993135, 0.76855016, 0.986257, 0.017444894, 0.5287075, 0.5601165, 0.1460432, 0.88569176, 0.07282839, 0.8348177,
-0.16016278, 0.031524524, 0.80207276, 0.37828946, 0.52338445, 0.6468418, 0.7837523, 0.00063179433, 0.17971309, 0.2897839,
-0.7161524, 0.3642513, 0.031674027, 0.8069974, 0.31171304, 0.8035024, 0.54259384, 0.9963711, 0.14053062, 0.6486664,
-0.19897254, 0.8962398, 0.43972084, 0.8936963, 0.46286246, 0.5031336, 0.8232569, 0.16667813, 0.19422211, 0.7717354,
-0.42838028, 0.19246033, 0.19039753, 0.8359823, 0.7296073, 0.9140669, 0.10166052, 0.29150867, 0.07212853, 0.54453945,
-0.40418974, 0.8114729, 0.08203155, 0.78043336, 0.7300014, 0.11568007, 0.73687613, 0.1792596, 0.70573187, 0.7252052,
-0.017522655, 0.14967212, 0.7451611, 0.42416203, 0.6358452, 0.26392296, 0.59180367, 0.9083765, 0.915427, 0.020250821,
-0.8235849, 0.6170742, 0.80640966, 0.40797767, 0.86140364, 0.52369213, 0.17385374, 0.19569172, 0.07739012, 0.3976461,
-0.70184183, 0.2510852, 0.92424256, 0.59599113, 0.24447663, 0.38749963, 0.81420827, 0.6592875, 0.16369487, 0.34718236,
-0.76625746, 0.6439973, 0.46094626, 0.46901694, 0.75421274, 0.27870816, 0.44729918, 0.76623553, 0.20013711, 0.46568435,
-0.32226324, 0.193284, 0.37608168, 0.051877704, 0.72095454, 0.7871155, 0.0050632227, 0.6740539, 0.9190297, 0.20630927,
-0.94182634, 0.5411844, 0.10186948, 0.30808574, 0.023363324, 0.7664375, 0.22542956, 0.14916998, 0.17968538, 0.24834555,
-0.44971466, 0.93251616, 0.74468166, 0.56824464, 0.25399336, 0.17958756, 0.15612793, 0.33739275, 0.6537649, 0.5826955,
-0.07639295, 0.40761822, 0.9955546, 0.6117058, 0.07538286, 0.50855786, 0.8750035, 0.8723649, 0.8750366, 0.4573611,
-0.38243642, 0.1401544, 0.7402578, 0.9573856, 0.40535605, 0.22507304, 0.54212785, 0.1528605, 0.44565362, 0.98777527,
-0.05327858, 0.2981292, 0.5865501, 0.9517916, 0.015969688, 0.38974705, 0.44860238, 0.807837, 0.79788435, 0.541367,
-0.6309876, 0.6676705, 0.02028897, 0.33633423, 0.12991633, 0.5342081, 0.5456298, 0.4901637, 0.2327029, 0.5148055,
-0.89143395, 0.35306472, 0.27413338, 0.7223243, 0.86590916, 0.30956024, 0.1922584, 0.787296, 0.1628886, 0.02892033,
-0.6374597, 0.0032674163, 0.89173913, 0.66598964, 0.5294169, 0.77826375, 0.8210681, 0.043763056, 0.5957361, 0.6856358,
-0.05995547, 0.06716649, 0.07448051, 0.3336696, 0.8263735, 0.7147659, 0.11986544, 0.40392354, 0.8274693, 0.87114793,
-0.67944324, 0.051964145, 0.9201576, 0.9308481, 0.096341334, 0.70021385, 0.02399584, 0.8642258, 0.08588241, 0.70640945,
-0.19748867, 0.6613063, 0.6449484, 0.768964, 0.9039073, 0.6277202, 0.77593136, 0.35429934, 0.8069173, 0.3516526,
-0.71314, 0.50186676, 0.8944276, 0.5470671, 0.45485002, 0.82426745, 0.2785842, 0.9404638, 0.8959508, 0.15114321,
-0.18969482, 0.78833485, 0.9598267, 0.29174066, 0.3494771, 0.5854956, 0.0831098, 0.960891, 0.56964827, 0.829203,
-0.7542679, 0.9568423, 0.9578806, 0.88932663, 0.48814714, 0.39864913, 0.42221805, 0.3055165, 0.42976233, 0.19865331,
-0.93883455, 0.7655661, 0.5970062, 0.4758167, 0.15800795, 0.17757647, 0.15753652, 0.3730905, 0.47599813, 0.27207386,
-0.42162967, 0.08353208, 0.96827507, 0.9347392, 0.51671463, 0.40915382, 0.7014796, 0.35320777, 0.4194869, 0.3184117,
-0.5446104, 0.81504035, 0.78465104, 0.9777143, 0.5973847, 0.7562977, 0.54398614, 0.0051009622, 0.05891997, 0.05620089,
-0.4020494, 0.9730677, 0.5107014, 0.69729745, 0.21230865, 0.4241287, 0.19132863, 0.48401004, 0.1337327, 0.17190064,
-0.42795905, 0.7100193, 0.48489287, 0.29757443, 0.40757337, 0.67073584, 0.98856723, 0.023141444, 0.37261203, 0.07899332,
-0.6971695, 0.06901029, 0.8860296, 0.11135061, 0.65404296, 0.12379419, 0.98091507, 0.6192919, 0.878432, 0.40171024,
-0.63359034, 0.15243557, 0.31417054, 0.41979724, 0.87002444, 0.44856197, 0.5728306, 0.2709776, 0.7224305, 0.09258589,
-0.21782517, 0.21746957, 0.21947508, 0.24758625, 0.8904527, 0.8345911, 0.3301475, 0.48707664, 0.57014096, 0.92664886,
-0.7677305, 0.5208447, 0.6324889, 0.97992665, 0.35903138, 0.3330391, 0.0870381, 0.39935082, 0.043254532, 0.08851445,
-0.44321367, 0.57203674, 0.60557806, 0.73202246, 0.5383103, 0.27552348, 0.39584875, 0.06509563, 0.42754996, 0.95901144,
-0.09790518, 0.7175897, 0.3007109, 0.28002614, 0.86116815, 0.47969994, 0.8495352, 0.63844335, 0.22089794, 0.8194518,
-0.7936467, 0.4938384, 0.049150985, 0.9517831, 0.6339798, 0.11274567, 0.51994663, 0.3342439, 0.060765848, 0.53698534,
-0.36152387, 0.17347981, 0.22772305, 0.6339161, 0.6493722, 0.64578843, 0.6118915, 0.48745263, 0.70927596, 0.6149292,
-0.43874234, 0.26505187, 0.05952667, 0.6111295, 0.8287437, 0.050140806, 0.22013378, 0.35246277, 0.1187585, 0.87933147,
-0.4835039, 0.44859475, 0.1784529, 0.2238027, 0.29486778, 0.9493753, 0.52288574, 0.65379494, 0.09804267, 0.42556462,
-0.75557685, 0.061604857, 0.0043297815, 0.8905646, 0.59748757, 0.92442536, 0.4898666, 0.6667948, 0.6306539, 0.21537969,
-0.8678084, 0.3620826, 0.9291674, 0.6059688, 0.3807095, 0.5285948, 0.43431175, 0.43802148, 0.123039424, 0.583839,
-0.8926119, 0.16748385, 0.2154854, 0.18143441, 0.05348144, 0.9129291, 0.99502695, 0.003920352, 0.33904833, 0.69999695,
-0.12290272, 0.9580966, 0.38940993, 0.2837113, 0.85935235, 0.37713748, 0.2607221, 0.16896206, 0.013641968, 0.90431833,
-0.5602742, 0.553339, 0.72180885, 0.9033788, 0.011523027, 0.1214213, 0.51942736, 0.57248414, 0.8430932, 0.76627296,
-0.5150635, 0.084864266, 0.5307555, 0.51420367, 0.5329527, 0.588093, 0.84611946, 0.82289535, 0.83708316, 0.68455845,
-0.9293985, 0.48594627, 0.32774645, 0.930657, 0.092476964, 0.9097118, 0.97267264, 0.6454561, 0.74661636, 0.003572011,
-0.2678727, 0.2653497, 0.4243795, 0.2187211, 0.023564778, 0.3392729, 0.44567502, 0.31210658, 0.16991138, 0.9320601,
-0.39350176, 0.42254278, 0.16082714, 0.57277536, 0.18493341, 0.03803846, 0.4273411, 0.87520623, 0.7507586, 0.27125937,
-0.531018, 0.43782672, 0.33187887, 0.32908353, 0.97491986, 0.07432794, 0.22559255, 0.7911518, 0.8109018, 0.10181122,
-0.14874865, 0.8739713, 0.8258678, 0.83952117, 0.49840027, 0.24971384, 0.6604848, 0.3120344, 0.4906389, 0.19367984,
-0.14241797, 0.5340129, 0.65298396, 0.90502304, 0.2910567, 0.50685567, 0.3251191, 0.7549711, 0.7457236, 0.054438505,
-0.4823707, 0.09746641, 0.8946975, 0.47535703, 0.472554, 0.83004594, 0.9334708, 0.09529597, 0.24380124, 0.9492368,
-0.11368034, 0.6545232, 0.5012047, 0.06810016, 0.7833115, 0.5195305, 0.59667504, 0.32130596, 0.07437508, 0.9352196,
-0.3775537, 0.11530671, 0.38456735, 0.5570788, 0.12884142, 0.9970051, 0.7848427, 0.42685586, 0.03802683, 0.4680642,
-0.7492088, 0.47062147, 0.045428254, 0.75646335, 0.6194405, 0.05128224, 0.9792738, 0.35051075, 0.3669672, 0.66835433,
-0.31624305, 0.56518877, 0.06823316, 0.5414021, 0.0799995, 0.4878948, 0.032808155, 0.5848838, 0.12171154, 0.7715262,
-0.9101807, 0.0038131434, 0.680596, 0.810504, 0.67688483, 0.36706397, 0.7128991, 0.3376187, 0.3465156, 0.47554886,
-0.04520323, 0.5066149, 0.05726915, 0.77573705, 0.200028, 0.6430589, 0.6090949, 0.7447414, 0.44865963, 0.73202926,
-0.5402566, 0.24616429, 0.9543388, 0.40602076, 0.61897653, 0.8123649, 0.047073558, 0.8431653, 0.47707924, 0.6409466,
-0.964197, 0.1999589, 0.3051443, 0.2665006, 0.5578835, 0.7453957, 0.7900255, 0.23492423, 0.07957853, 0.25237653,
-0.33838317, 0.6416551, 0.0039951354, 0.89141834, 0.62315106, 0.80962807, 0.50791967, 0.29249611, 0.34137407, 0.4369406,
-0.8787999, 0.28806677, 0.1362242, 0.3896823, 0.23126958, 0.66401637, 0.049474377, 0.27457523, 0.19152752, 0.8645199,
-0.31999043, 0.8697338, 0.8605395, 0.70556897, 0.5113519, 0.84524435, 0.20147063, 0.79076856, 0.21785353, 0.4546323,
-0.8530334, 0.3741707, 0.66516286, 0.1962831, 0.3936461, 0.89860153, 0.24216916, 0.062920436, 0.7828697, 0.8093484,
-0.30444527, 0.75457746, 0.5017912, 0.040138636, 0.7621467, 0.6761302, 0.06373471, 0.915462, 0.035231, 0.89386714,
-0.6959213, 0.51545024, 0.04339671, 0.21505861, 0.9323861, 0.46864936, 0.7811156, 0.29842615, 0.38006642, 0.7779068,
-0.60815746, 0.7171511, 0.07464257, 0.88674176, 0.5839072, 0.5046292, 0.6229039, 0.9399411, 0.9960362, 0.33266804,
-0.42184722, 0.9865539, 0.49170554, 0.38217908, 0.5600747, 0.565413, 0.36794263, 0.82040083, 0.94342226, 0.8352217,
-0.78150964, 0.2860086, 0.75553757, 0.32398638, 0.758711, 0.3375832, 0.33077398, 0.45010427, 0.26389697, 0.92499673,
-0.11748593, 0.943743, 0.682854, 0.004962936, 0.20119096, 0.58729416, 0.67993486, 0.6150494, 0.45623145, 0.25751752,
-0.053226303, 0.12379362, 0.91942585, 0.702563, 0.47201994, 0.7093674, 0.023744669, 0.66121763, 0.65498394, 0.36697313,
-0.10070673, 0.96071476, 0.3550039, 0.54484475, 0.99639714, 0.32214886, 0.96161354, 0.7506562, 0.12803078, 0.24632397,
-0.17385522, 0.17279965, 0.6760441, 0.071039446, 0.2151821, 0.4781042, 0.30369994, 0.48674262, 0.18098812, 0.97278047,
-0.8854781, 0.7528932, 0.3641694, 0.68590474, 0.7819954, 0.657716, 0.36658275, 0.05297459, 0.85196644, 0.049343612,
-0.31383854, 0.6695563, 0.7951203, 0.89692384, 0.82429004, 0.15677115, 0.5887391, 0.13800927, 0.0085657975, 0.8790421,
-0.6256806, 0.9292787, 0.48701864, 0.20990747, 0.083662316, 0.88042665, 0.4477495, 0.8483864, 0.48738086, 0.99391574,
-0.40566745, 0.537002, 0.4802295, 0.6822035, 0.48149505, 0.34781352, 0.5965454, 0.66909915, 0.76284933, 0.33868113,
-0.9555661, 0.90863895, 0.89868975, 0.07868716, 0.93248546, 0.50429887, 0.37767935, 0.77912027, 0.24674945, 0.05841095,
-0.8893651, 0.16569066, 0.4781768, 0.301946, 0.34709984, 0.9561994, 0.26587456, 0.15426192, 0.6022424, 0.9015687,
-0.20996648, 0.51819634, 0.5655937, 0.8580507, 0.64367616, 0.7768365, 0.18932684, 0.11291685, 0.4154288, 0.4764765,
-0.5602257, 0.91964, 0.37515992, 0.6698847, 0.923476, 0.7170417, 0.030588947, 0.40833148, 0.27742204, 0.57936347,
-0.5027473, 0.6686292, 0.60163695, 0.42896992, 0.10455062, 0.2399768, 0.058825243, 0.17828348, 0.3351036, 0.5252956,
-0.08193896, 0.44228348, 0.06685673, 0.8612806, 0.12871465, 0.43736976, 0.34304523, 0.040639006, 0.435011, 0.15564895,
-0.314972, 0.2647625, 0.36369145, 0.770273, 0.4981852, 0.96972513, 0.79053074, 0.80829215, 0.37847006, 0.63005817,
-0.9256105, 0.85754305, 0.8768399, 0.022878975, 0.3988214, 0.54133725, 0.9165594, 0.1366238, 0.7535001, 0.40369937,
-0.71801126, 0.011043364, 0.77781326, 0.89013314, 0.39453754, 0.11794228, 0.85278326, 0.5138793, 0.54117, 0.4861062,
-0.37399647, 0.98994994, 0.9733205, 0.12177309, 0.26439142, 0.23798482, 0.30493778, 0.83136404, 0.9307847, 0.13482551,
-0.44944605, 0.25053307, 0.7998134, 0.70504546, 0.5996852, 0.22439589, 0.5654436, 0.043977752, 0.4624592, 0.5873774,
-0.52081037, 0.20642142, 0.2871389, 0.031311635, 0.43763772, 0.30392867, 0.48694924, 0.4735583, 0.37573543, 0.3802429,
-0.11694187, 0.27665144, 0.26712215, 0.89236385, 0.25606167, 0.93566054, 0.8842226, 0.7550668, 0.7584876, 0.16083659,
-0.23639946, 0.08519537, 0.20583908, 0.6186746, 0.9542533, 0.46747816, 0.21122995, 0.07276781, 0.29044798, 0.17014165,
-0.5524987, 0.8088055, 0.0514201, 0.9537926, 0.9652958, 0.16757506, 0.70281106, 0.94200885, 0.6841354, 0.96046275,
-0.7510356, 0.8313795, 0.45562857, 0.5505418, 0.017883644, 0.17279461, 0.9834109, 0.90744954, 0.44898376, 0.66402465,
-0.34017327, 0.81037676, 0.28549019, 0.3016226, 0.35097796, 0.43561503, 0.00058234343, 0.6684643, 0.07705832, 0.97015953,
-0.092698716, 0.41418144, 0.18311031, 0.20559378, 0.82774425, 0.30813637, 0.22523133, 0.31332958, 0.92706805, 0.08848662,
-0.23284948, 0.9422138, 0.07093142, 0.7980248, 0.409801, 0.40501997, 0.6295668, 0.6552973, 0.600791, 0.7814587,
-0.48406723, 0.3037804, 0.62378407, 0.62642336, 0.82996833, 0.7421219, 0.5233153, 0.74979746, 0.6028146, 0.5296808,
-0.16699271, 0.03434674, 0.86495054, 0.71397585, 0.86776406, 0.33685416, 0.6482692, 0.2500348, 0.7227976, 0.70974725,
-0.9475633, 0.6700813, 0.9803815, 0.36049715, 0.43117517, 0.39795953, 0.7394454, 0.4874654, 0.8918216, 0.94595796,
-0.8060482, 0.3452851, 0.06767335, 0.29559964, 0.4860923, 0.7889183, 0.7903974, 0.556687, 0.3756254, 0.08562232,
-0.7848211, 0.47543386, 0.71051496, 0.3973873, 0.9214939, 0.19850273, 0.07726323, 0.3569556, 0.9302608, 0.072946854,
-0.7567508, 0.37953198, 0.9324997, 0.89104366, 0.8338954, 0.8139859, 0.32339892, 0.2632869, 0.19524816, 0.43200883,
-0.002676534, 0.035849903, 0.8579759, 0.65685666, 0.7236325, 0.82170767, 0.9666734, 0.5693509, 0.22788355, 0.07884572,
-0.54645675, 0.09158218, 0.8744094, 0.63717526, 0.9249262, 0.47212943, 0.9595664, 0.58299416, 0.43900326, 0.23267244,
-0.3206963, 0.3824898, 0.55720466, 0.8188748, 0.18920717, 0.42651626, 0.41278538, 0.17662966, 0.46170422, 0.6721064,
-0.4655194, 0.5271105, 0.3614388, 0.94361657, 0.08294579, 0.74897116, 0.617458, 0.053658314, 0.67375475, 0.09978627,
-0.23182935, 0.50791234, 0.12907204, 0.85141504, 0.5264901, 0.66516864, 0.50512254, 0.29532441, 0.9661175, 0.36176598,
-0.8544195, 0.7404047, 0.82428366, 0.96257573, 0.11131253, 0.62018675, 0.47864527, 0.039101128, 0.46764946, 0.29711628,
-0.40892226, 0.7900437, 0.10764668, 0.55577713, 0.6133263, 0.019346252, 0.73014337, 0.9307928, 0.5542295, 0.17595504,
-0.8546715, 0.90590805, 0.9092394, 0.33921698, 0.0008430821, 0.81278396, 0.25341776, 0.7057896, 0.29238465, 0.52403855,
-0.9213937, 0.11746097, 0.21051219, 0.09993823, 0.8176869, 0.72511464, 0.70282686, 0.3988631, 0.83230406, 0.46275905,
-0.2703259, 0.57835686, 0.58600885, 0.3766385, 0.690864, 0.44178563, 0.40026566, 0.5732949, 0.23808873, 0.50714386,
-0.9350253, 0.57432973, 0.74109495, 0.79016244, 0.5070945, 0.9485114, 0.8311653, 0.48506665, 0.9617326, 0.29852858,
-0.366769, 0.77285564, 0.74671644, 0.94361097, 0.3757226, 0.29146126, 0.57953155, 0.007708449, 0.7380902, 0.88821167,
-0.31651938, 0.33128026, 0.09848877, 0.09147043, 0.90562916, 0.27631462, 0.31989923, 0.53260094, 0.648353, 0.5590575,
-0.4125183, 0.68012285, 0.4677009, 0.7852408, 0.5890133, 0.34706393, 0.37636602, 0.42034975, 0.5928437, 0.86917543,
-0.89394933, 0.21776019, 0.43713045, 0.5337755, 0.09599007, 0.49747026, 0.83164036, 0.6423979, 0.00091591524, 0.39940274,
-0.8622541, 0.3925572, 0.83520466, 0.3498771, 0.19062445, 0.603745, 0.475841, 0.6496245, 0.8845333, 0.2307799,
-0.6286122, 0.29856437, 0.83671373, 0.40267518, 0.8860103, 0.6866461, 0.30515477, 0.9614757, 0.3545977, 0.028658632,
-0.9150952, 0.15918177, 0.41486475, 0.8689148, 0.9942623, 0.0987592, 0.8941498, 0.5647133, 0.99548036, 0.40815887,
-0.44467425, 0.6775013, 0.531685, 0.24895021, 0.69680333, 0.019961093, 0.8449182, 0.1178238, 0.59461635, 0.98526824,
-0.871223, 0.7267415, 0.53581643, 0.3620638, 0.24056326, 0.59538496, 0.38104647, 0.034455262, 0.6477652, 0.40934396,
-0.19231549, 0.8701647, 0.28780022, 0.97225726, 0.48430753, 0.7030723, 0.9776925, 0.9662899, 0.3556148, 0.09186526,
-0.7095952, 0.9111277, 0.65414417, 0.47637445, 0.78610563, 0.9511109, 0.7668794, 0.5877635, 0.7058718, 0.8660492,
-0.8417279, 0.18733096, 0.3668593, 0.36932942, 0.15743567, 0.18835372, 0.62336534, 0.05280094, 0.6283515, 0.3988773,
-0.7177127, 0.85969454, 0.9169481, 0.5861364, 0.21584338, 0.5745095, 0.3897011, 0.55942774, 0.7646427, 0.993731,
-0.042268623, 0.8786283, 0.762209, 0.5027511, 0.27567303, 0.9600953, 0.072597355, 0.059442017, 0.57595813, 0.2894524,
-0.82850564, 0.793283, 0.32858342, 0.78171605, 0.56761605, 0.0049845274, 0.50330544, 0.9184708, 0.8148216, 0.29595378,
-0.07970701, 0.92489153, 0.33793837, 0.9567375, 0.37415254, 0.84990066, 0.9941796, 0.06800775, 0.26053104, 0.21159613,
-0.5614098, 0.20745164, 0.8231208, 0.7121408, 0.82378054, 0.9630996, 0.42512196, 0.8641082, 0.09365638, 0.19734041,
-0.11575636, 0.5639233, 0.4768428, 0.33889914, 0.5703717, 0.9244297, 0.5311111, 0.13523202, 0.01852037, 0.21085885,
-0.071204096, 0.4712303, 0.74460614, 0.4686889, 0.914024, 0.117377095, 0.54068995, 0.80547154, 0.12859856, 0.4257724,
-0.9659156, 0.0045896024, 0.798911, 0.36436203, 0.7280426, 0.621054, 0.9701622, 0.6164426, 0.9579355, 0.6045164,
-0.5798626, 0.63919723, 0.82481444, 0.61748123, 0.18019743, 0.5157837, 0.44804874, 0.99903923, 0.3863658, 0.44972283,
-0.31878954, 0.85894763, 0.049487386, 0.04967219, 0.14039204, 0.09017946, 0.4628455, 0.3544319, 0.7981168, 0.70640343,
-0.42240968, 0.6196504, 0.73550963, 0.667884, 0.23142478, 0.11116676, 0.7650123, 0.112480775, 0.6108565, 0.9493177,
-0.9542675, 0.9146685, 0.17729652, 0.41400397, 0.6309963, 0.43200687, 0.6464159, 0.12712492, 0.2884915, 0.3982403,
-0.66932833, 0.54165065, 0.4191057, 0.67887574, 0.10698286, 0.10696802, 0.9551022, 0.7492388, 0.22396998, 0.63786316,
-0.15820846, 0.6157303, 0.8183258, 0.25153205, 0.18210672, 0.9602121, 0.9036876, 0.15693043, 0.38605642, 0.06903067,
-0.7507714, 0.33556795, 0.38818276, 0.43704808, 0.4954553, 0.40412104, 0.6816511, 0.63548344, 0.4186759, 0.70838517,
-0.44376358, 0.3357206, 0.06594042, 0.39987648, 0.037075095, 0.88075906, 0.20054473, 0.05663389, 0.5609011, 0.124456756,
-0.15606454, 0.015773552, 0.88851076, 0.9729933, 0.79110926, 0.33853722, 0.09634267, 0.9257645, 0.23189723, 0.6707842,
-0.52831924, 0.48948547, 0.7410685, 0.2194608, 0.6474689, 0.3337604, 0.15346791, 0.98205763, 0.18342042, 0.70286185,
-0.42531693, 0.3196188, 0.3305629, 0.5155848, 0.19409959, 0.82248783, 0.5497899, 0.41844934, 0.21445695, 0.3013477,
-0.7596674, 0.8470537, 0.5960293, 0.26159966, 0.91296613, 0.7349978, 0.44705716, 0.41518942, 0.6459388, 0.1569181,
-0.30777836, 0.7558866, 0.4035862, 0.7478917, 0.18006596, 0.9542781, 0.5946521, 0.8464796, 0.75240755, 0.7033147,
-0.7272911, 0.2184871, 0.87321347, 0.8580393, 0.69913983, 0.83644575, 0.68521065, 0.372926, 0.77889377, 0.96862143,
-0.7887473, 0.67789334, 0.7113075, 0.93054956, 0.9111168, 0.6812655, 0.89345616, 0.47946882, 0.30649468, 0.9124711,
-0.88670325, 0.7382785, 0.33611885, 0.026502334, 0.39508346, 0.6694303, 0.9160326, 0.5826711, 0.33551884, 0.23982148,
-0.22783574, 0.70331025, 0.6660418, 0.51114225, 0.57405657, 0.5411803, 0.9738403, 0.73799, 0.5624598, 0.07652036,
-0.04978715, 0.07413118, 0.6362957, 0.6773174, 0.36817077, 0.629885, 0.044579085, 0.47303665, 0.836775, 0.49880046,
-0.06082195, 0.115183294, 0.53998494, 0.83993644, 0.81661147, 0.98901266, 0.88236827, 0.84671116, 0.46295583, 0.029709496,
-0.9204132, 0.10253954, 0.03740714, 0.5390723, 0.74078566, 0.08543706, 0.011851499, 0.20016527, 0.356493, 0.36993647,
-0.70742524, 0.15546617, 0.917009, 0.22997431, 0.86268395, 0.81257206, 0.1019828, 0.65880144, 0.6583316, 0.7651984,
-0.6248512, 0.44299594, 0.74589616, 0.8367184, 0.17899951, 0.11265245, 0.16332534, 0.8261054, 0.6945308, 0.5850439,
-0.65881205, 0.12712914, 0.27503416, 0.53275037, 0.15610719, 0.9472476, 0.036724042, 0.0972234, 0.9365317, 0.2827337,
-0.6180335, 0.8444138, 0.116543666, 0.46683854, 0.7913752, 0.9053558, 0.19817433, 0.3100106, 0.9772525, 0.0040394296,
-0.8870298, 0.22356682, 0.18837956, 0.6977574, 0.40485826, 0.47741726, 0.35664338, 0.20068875, 0.36007276, 0.62813324,
-0.92211175, 0.1857461, 0.5056345, 0.7714491, 0.7111244, 0.5802961, 0.880432, 0.3842586, 0.07386713, 0.9154364,
-0.775848, 0.0047594067, 0.7222697, 0.37559786, 0.14716488, 0.7804374, 0.32645226, 0.27905762, 0.04534316, 0.27364373,
-0.9144781, 0.8533147, 0.84885293, 0.6904914, 0.6980141, 0.43524522, 0.93874955, 0.57727677, 0.1278921, 0.67868996,
-0.5906042, 0.8360353, 0.73715067, 0.30839851, 0.360622, 0.43228745, 0.33877933, 0.3450946, 0.7557141, 0.21107915,
-0.024923787, 0.8139157, 0.23614348, 0.061816096, 0.22819144, 0.88227046, 0.5012971, 0.8127817, 0.55059254, 0.6244208,
-0.15096499, 0.07758577, 0.15534559, 0.08642902, 0.7136551, 0.068797, 0.33689317, 0.8151431, 0.073435, 0.27587917,
-0.6415465, 0.30315524, 0.25636652, 0.3951772, 0.32483214, 0.9398127, 0.26760876, 0.41387123, 0.014975904, 0.7148774,
-0.4416581, 0.9813577, 0.5233435, 0.83426404, 0.24871995, 0.100562416, 0.6171712, 0.78703684, 0.4622999, 0.8157436,
-0.93394816, 0.1259679, 0.026684225, 0.50347126, 0.527725, 0.5130184, 0.6806897, 0.6507216, 0.59474343, 0.29182497,
-0.09539426, 0.52363616, 0.27165958, 0.47983494, 0.56953263, 0.72176856, 0.5575492, 0.8409663, 0.73698395, 0.28837872,
-0.6146617, 0.08742587, 0.7978058, 0.8357151, 0.18276273, 0.16960731, 0.55424225, 0.32108158, 0.83770907, 0.61309266,
-0.45162576, 0.54985636, 0.35284323, 0.25769138, 0.34193105, 0.5155786, 0.27647102, 0.75289524, 0.86745226, 0.8118137,
-0.259123, 0.61688715, 0.8191278, 0.7231509, 0.6194832, 0.9180219, 0.7096981, 0.043508567, 0.26473138, 0.5269514,
-0.5430132, 0.77620494, 0.05005288, 0.1739212, 0.20108196, 0.8465223, 0.32816213, 0.19096912, 0.32070854, 0.35811764,
-0.9587762, 0.3596081, 0.81301254, 0.9816507, 0.84019923, 0.54553795, 0.17079297, 0.013968218, 0.13790388, 0.053954035,
-0.44529754, 0.80465394, 0.9735141, 0.92517024, 0.029255724, 0.99777454, 0.26829806, 0.07465485, 0.21623193, 0.2647408,
-0.45990923, 0.5107337, 0.056350194, 0.31075767, 0.07007945, 0.6754208, 0.49980345, 0.17892201, 0.056609415, 0.4954088,
-0.18741646, 0.08550189, 0.4321867, 0.5093346, 0.85303754, 0.89951485, 0.8038746, 0.8374771, 0.88295174, 0.073945254,
-0.7472289, 0.69572985, 0.90560466, 0.21077734, 0.08165387, 0.7383593, 0.80269086, 0.12488264, 0.14466548, 0.20330743,
-0.5782242, 0.2535073, 0.9747372, 0.055967752, 0.8982084, 0.44804245, 0.30325794, 0.50225484, 0.91157126, 0.16477837,
-0.045734458, 0.99187094, 0.9573588, 0.6424951, 0.8665376, 0.35979563, 0.37246728, 0.46417946, 0.0721327, 0.12974085,
-0.19389993, 0.430821, 0.19170313, 0.14228667, 0.51751184, 0.76417935, 0.605129, 0.8455728, 0.2291038, 0.3317202,
-0.87272996, 0.37492082, 0.034256544, 0.853302, 0.9171846, 0.9339092, 0.11076469, 0.37621894, 0.6111262, 0.40499508,
-0.5962569, 0.30161974, 0.92590576, 0.7181733, 0.028210793, 0.755358, 0.7383711, 0.2631096, 0.34423977, 0.7218582,
-0.365892, 0.3385114, 0.05274994, 0.014924624, 0.0094075035, 0.1474032, 0.061804168, 0.8324505, 0.5384559, 0.13402902,
-0.84291345, 0.45768508, 0.27315107, 0.5798511, 0.29204842, 0.6708136, 0.9576144, 0.10405682, 0.7253105, 0.9326284,
-0.24903095, 0.99624836, 0.8530533, 0.6671376, 0.5334839, 0.8922802, 0.50491524, 0.47352976, 0.114075884, 0.76215386,
-0.025808325, 0.34201944, 0.50133306, 0.5072456, 0.9658282, 0.53421855, 0.32217088, 0.019331919, 0.8438945, 0.7697814,
-0.872105, 0.27831417, 0.837763, 0.47709718, 0.56208163, 0.13857186, 0.028468672, 0.34605467, 0.42612493, 0.35739717,
-0.79774356, 0.63431424, 0.5377991, 0.4116114, 0.4728273, 0.36964366, 0.48545814, 0.3856123, 0.48144072, 0.11712731,
-0.64248794, 0.5882744, 0.71837467, 0.77630204, 0.1082207, 0.500894, 0.956352, 0.7659055, 0.6140229, 0.75782984,
-0.34864277, 0.9382825, 0.26016235, 0.9555291, 0.06052337, 0.9707168, 0.15848531, 0.3759561, 0.10505597, 0.39491206,
-0.86381155, 0.15886053, 0.047404833, 0.7566787, 0.96441025, 0.3914941, 0.8042203, 0.08972167, 0.0344183, 0.59618455,
-0.0487604, 0.93655854, 0.5378912, 0.7267672, 0.12729345, 0.2838306, 0.5599395, 0.06146098, 0.3688765, 0.061187647,
-0.18221985, 0.2625632, 0.7320318, 0.6682951, 0.008754399, 0.85946107, 0.3741519, 0.58227, 0.35108802, 0.5021105,
-0.21115834, 0.10950206, 0.28055635, 0.08652866, 0.25331578, 0.48362744, 0.5408696, 0.9616959, 0.8118918, 0.7167266,
-0.6966737, 0.8666303, 0.73148715, 0.017838325, 0.7090695, 0.4120842, 0.40039128, 0.5333952, 0.8282356, 0.77669275,
-0.41077727, 0.09702433, 0.007079605, 0.043868326, 0.21269222, 0.6012483, 0.42682874, 0.37910977, 0.7479243, 0.10494917,
-0.01734221, 0.22195028, 0.73863363, 0.5323078, 0.38502622, 0.93925834, 0.6560022, 0.45136255, 0.47345138, 0.643666,
-0.74296105, 0.5982436, 0.24956919, 0.65214986, 0.36451396, 0.31558952, 0.531076, 0.71419346, 0.9592256, 0.5966702,
-0.45906982, 0.8407567, 0.7540344, 0.5743953, 0.09133322, 0.114134, 0.10242245, 0.23668802, 0.87383646, 0.6520674,
-0.056798704, 0.16175981, 0.2137716, 0.7069426, 0.6993844, 0.4747234, 0.1279967, 0.19917937, 0.6328121, 0.76981115,
-0.756082, 0.94902873, 0.059943788, 0.1845696, 0.03373171, 0.8125337, 0.84745514, 0.35492972, 0.67935437, 0.8971027,
-0.07017233, 0.7126353, 0.41988418, 0.15125412, 0.6458793, 0.1765855, 0.46791586, 0.16423836, 0.4409746, 0.27089223,
-0.83683586, 0.4193142, 0.5775261, 0.82138395, 0.58686733, 0.58120126, 0.384472, 0.54262656, 0.95276546, 0.8897906,
-0.1875928, 0.33189663, 0.08138137, 0.18941447, 0.8405882, 0.51004106, 0.7808129, 0.5694648, 0.54066354, 0.27879953,
-0.26667887, 0.74749273, 0.55733365, 0.97673374, 0.5818951, 0.34416345, 0.74187565, 0.06251747, 0.061063267, 0.5227989,
-0.0068075284, 0.96375835, 0.75820476, 0.36191988, 0.93297523, 0.3367678, 0.37150264, 0.23855984, 0.5977023, 0.45253047,
-0.42806166, 0.30482855, 0.40216422, 0.7895638, 0.7095099, 0.7382757, 0.6312539, 0.23046969, 0.3106659, 0.13583827,
-0.39577258, 0.89845103, 0.6235748, 0.16217506, 0.004213362, 0.08934315, 0.86198056, 0.60079235, 0.23948883, 0.24270387,
-0.8393256, 0.32195452, 0.4815633, 0.4299666, 0.8829831, 0.22383447, 0.57369184, 0.7194615, 0.2564392, 0.5038204,
-0.13853844, 0.5422531, 0.97176254, 0.0881331, 0.85073787, 0.9618503, 0.3453285, 0.76776993, 0.26722383, 0.8436194,
-0.7129096, 0.51140594, 0.75185156, 0.925225, 0.1270263, 0.10835649, 0.34018353, 0.5960297, 0.35770652, 0.8436321,
-0.47478724, 0.7707103, 0.999071, 0.35499844, 0.6132049, 0.106107146, 0.82326525, 0.97219765, 0.9065807, 0.48567542,
-0.16458383, 0.9117924, 0.9740305, 0.8068454, 0.99729985, 0.8535195, 0.9266885, 0.5354417, 0.3114372, 0.04236306,
-0.7440147, 0.09421062, 0.3335685, 0.3958694, 0.52979434, 0.32791966, 0.57010293, 0.5563383, 0.30294028, 0.77462655,
-0.88365096, 0.97766215, 0.36175498, 0.41280714, 0.029033197, 0.36782816, 0.5431821, 0.61676407, 0.47492823, 0.7446307,
-0.13858505, 0.37313086, 0.86118925, 0.7815484, 0.6790356, 0.8011172, 0.53737545, 0.94500613, 0.92792517, 0.27350682,
-0.18166798, 0.8047418, 0.2845925, 0.31534344, 0.09961744, 0.38057664, 0.43714178, 0.6032016, 0.82520413, 0.28528523,
-0.5360042, 0.26692694, 0.66925734, 0.13195412, 0.6020245, 0.18692169, 0.5500374, 0.5612233, 0.77781224, 0.62947166,
-0.31033742, 0.30992442, 0.060513485, 0.5668065, 0.903778, 0.3708838, 0.2330214, 0.55202013, 0.71683383, 0.72867715,
-0.79054415, 0.6250968, 0.62841314, 0.029433481, 0.59295857, 0.07890911, 0.69306964, 0.046411548, 0.3131897, 0.6484566,
-0.9306864, 0.93998045, 0.79156, 0.189643, 0.20862652, 0.8716581, 0.7038735, 0.7292351, 0.1795239, 0.49211392,
-0.25107977, 0.9761521, 0.16719387, 0.29845348, 0.9631694, 0.87174356, 0.74422836, 0.7177861, 0.41156542, 0.72873366,
-0.14755523, 0.88512164, 0.8863678, 0.096526965, 0.49474105, 0.9109074, 0.6385138, 0.63982385, 0.53899556, 0.5231154,
-0.49385205, 0.5036258, 0.24803366, 0.12935568, 0.6987853, 0.37035698, 0.5183644, 0.8708705, 0.35817996, 0.032119915,
-0.66701025, 0.5037863, 0.37249622, 0.22471993, 0.47759736, 0.81439203, 0.45790294, 0.32995966, 0.06626411, 0.721215,
-0.33468077, 0.97528356, 0.6348461, 0.584456, 0.50090134, 0.04556473, 0.053612676, 0.695033, 0.69490194, 0.29771915,
-0.23314431, 0.064049676, 0.19023955, 0.6564085, 0.99826187, 0.7474539, 0.7281185, 0.037838195, 0.5996682, 0.5928124,
-0.35337916, 0.87335783, 0.3596061, 0.37944552, 0.06172341, 0.6437689, 0.51262546, 0.66164786, 0.6189296, 0.680349,
-0.45300442, 0.3085541, 0.57355976, 0.81778055, 0.18843463, 0.51856846, 0.8687797, 0.6635776, 0.6284543, 0.6532206,
-0.3167443, 0.8233314, 0.17596854, 0.06046078, 0.7989756, 0.6029606, 0.31354675, 0.7160877, 0.22645807, 0.7301434,
-0.086273566, 0.42006475, 0.7302915, 0.4734517, 0.36783585, 0.4613229, 0.6156775, 0.2554006, 0.5227326, 0.8571324,
-0.53293926, 0.39196482, 0.07610343, 0.014552955, 0.84471476, 0.9245902, 0.49048993, 0.37245902, 0.4679739, 0.47969338,
-0.8786742, 0.06454086, 0.40938383, 0.9464476, 0.2760681, 0.5300478, 0.6973893, 0.2991453, 0.5804699, 0.45876285,
-0.33022216, 0.79653776, 0.43518978, 0.8887862, 0.59407544, 0.032939672, 0.5782626, 0.10010804, 0.44994467, 0.7271117,
-0.902891, 0.6133791, 0.140845, 0.77132195, 0.12028129, 0.9247795, 0.74722797, 0.16141559, 0.21574605, 0.8743854,
-0.11247064, 0.9410877, 0.24811381, 0.74676466, 0.8514692, 0.021732707, 0.010680916, 0.7838439, 0.19738361, 0.8377881,
-0.7639336, 0.31653216, 0.6749307, 0.06396978, 0.52691025, 0.7364015, 0.956775, 0.18731725, 0.42047754, 0.8117751,
-0.34632754, 0.39038187, 0.9225143, 0.7408622, 0.57680243, 0.2652951, 0.92369586, 0.6380619, 0.82616633, 0.35128862,
-0.7828198, 0.5359737, 0.08339928, 0.7060845, 0.3462922, 0.38913444, 0.54842395, 0.6884251, 0.037316978, 0.5723427,
-0.022258755, 0.79441875, 0.90272444, 0.61215657, 0.9631781, 0.5863588, 0.9384484, 0.07687521, 0.24441172, 0.38387978,
-0.96800447, 0.5599107, 0.74093807, 0.403971, 0.5280579, 0.72208875, 0.018573398, 0.5072516, 0.16996226, 0.58617413,
-0.09803684, 0.37261903, 0.95767754, 0.84609497, 0.05496832, 0.22795987, 0.23313288, 0.9688462, 0.7176776, 0.1377758,
-0.18797757, 0.26834992, 0.15000027, 0.8481348, 0.7895163, 0.5519088, 0.48765746, 0.31035778, 0.77768403, 0.9904436,
-0.32684666, 0.84682065, 0.39365014, 0.44228655, 0.38328415, 0.22290905, 0.79503566, 0.6794283, 0.17802662, 0.62420344,
-0.37056103, 0.041172326, 0.51846284, 0.45114288, 0.47430587, 0.6496397, 0.8367412, 0.05662944, 0.5571883, 0.7352182,
-0.35322595, 0.9696022, 0.35919765, 0.10663593, 0.19590221, 0.6996546, 0.40991047, 0.89280325, 0.6144547, 0.9761491,
-0.23443131, 0.70821565, 0.7295676, 0.17951865, 0.25932744, 0.25121617, 0.97896886, 0.515391, 0.46281084, 0.83205926,
-0.4329242, 0.55370456, 0.7908196, 0.093474135, 0.7672148, 0.14680524, 0.74988705, 0.69885737, 0.37382892, 0.13987659,
-0.7151676, 0.431028, 0.75316954, 0.04246583, 0.63721764, 0.35724443, 0.48762304, 0.28701422, 0.24638435, 0.6836296,
-0.8129986, 0.9022324, 0.064973645, 0.20187753, 0.38977212, 0.6623454, 0.31160477, 0.3389442, 0.19181544, 0.2230897,
-0.6706708, 0.32135025, 0.5938186, 0.725129, 0.30229402, 0.7995213, 0.17878264, 0.2657235, 0.33942115, 0.04909697,
-0.94976753, 0.7110531, 0.5189743, 0.47457805, 0.2609815, 0.8034033, 0.9550461, 0.6871017, 0.542301, 0.90208304,
-0.76359314, 0.6919547, 0.2690066, 0.77918124, 0.019060668, 0.5306918, 0.48873094, 0.58894205, 0.703702, 0.104869366,
-0.8352005, 0.41094282, 0.507042, 0.15073924, 0.46920577, 0.3938173, 0.8372094, 0.028040525, 0.7401718, 0.8376963,
-0.17846179, 0.22189952, 0.9475931, 0.19728738, 0.7338621, 0.101945534, 0.3832581, 0.59039557, 0.94089603, 0.5863688,
-0.7072993, 0.624503, 0.7966432, 0.28973243, 0.45949653, 0.9787162, 0.052343633, 0.81463736, 0.70606834, 0.7716022,
-0.31079042, 0.5898406, 0.5620215, 0.23455179, 0.21389648, 0.5388247, 0.2040111, 0.36823508, 0.0053723096, 0.8671642,
-0.9661939, 0.9270056, 0.94692993, 0.7046047, 0.72362125, 0.5416936, 0.7443616, 0.07171923, 0.04531915, 0.91711515,
-0.1474337, 0.89833534, 0.648046, 0.11733318, 0.39757007, 0.21069747, 0.6142996, 0.21730955, 0.6912427, 0.49048957,
-0.34147367, 0.022572042, 0.3219722, 0.9685696, 0.5269059, 0.5886212, 0.659878, 0.7130413, 0.98339087, 0.19503741,
-0.89793444, 0.015023004, 0.5850233, 0.07373183, 0.62017494, 0.7802937, 0.6775731, 0.09203854, 0.5661112, 0.9178029,
-0.2343546, 0.9806244, 0.7693182, 0.7889532, 0.6241685, 0.41245508, 0.9417946, 0.44468832, 0.8369817, 0.0031990237,
-0.9245251, 0.98670155, 0.6769924, 0.51488274, 0.5256905, 0.9436219, 0.6050334, 0.97836035, 0.17769879, 0.13500004,
-0.8818156, 0.0313203, 0.08832834, 0.8502817, 0.019180698, 0.13241069, 0.31331208, 0.5743142, 0.49715826, 0.6172764,
-0.5331244, 0.5222611, 0.6511984, 0.7734398, 0.256135, 0.3608493, 0.25325385, 0.533019, 0.34440103, 0.114450805,
-0.6468266, 0.2151897, 0.8760596, 0.9801919, 0.27051234, 0.9112329, 0.3380306, 0.07014053, 0.54804134, 0.6765531,
-0.1752603, 0.69921273, 0.9143398, 0.43111116, 0.035987273, 0.2030343, 0.8922961, 0.91903645, 0.76977247, 0.49175784,
-0.099143006, 0.3674804, 0.94753003, 0.21970531, 0.47007462, 0.40226397, 0.3355032, 0.9035526, 0.25874776, 0.16484123,
-0.69036806, 0.07201438, 0.63395935, 0.063247986, 0.48817343, 0.6666259, 0.15526073, 0.10813647, 0.5797694, 0.10794782,
-0.79438007, 0.24317154, 0.026272861, 0.8206052, 0.4420161, 0.8339117, 0.6079213, 0.22008722, 0.73745257, 0.053100668,
-0.46855322, 0.33421737, 0.76324654, 0.8526432, 0.015307797, 0.27934623, 0.26765963, 0.65635425, 0.51011723, 0.86824834,
-0.57572967, 0.43447804, 0.8113928, 0.38320008, 0.986185, 0.10324592, 0.06525337, 0.85109174, 0.94293773, 0.36936134,
-0.047773577, 0.7841596, 0.33926708, 0.66182464, 0.69737774, 0.85597146, 0.34120753, 0.12692484, 0.7776892, 0.63616294,
-0.79434264, 0.11541597, 0.16610004, 0.2056471, 0.696288, 0.35615066, 0.30876786, 0.78131616, 0.04794019, 0.2088272,
-0.39896628, 0.49890646, 0.59801924, 0.711521, 0.5322181, 0.35990205, 0.43177876, 0.6430728, 0.8344202, 0.33877015,
-0.76865834, 0.75682956, 0.2771495, 0.3680912, 0.005327093, 0.68439364, 0.9949503, 0.10142185, 0.15526544, 0.15933633,
-0.9381387, 0.14073479, 0.87866503, 0.8739543, 0.07390571, 0.46031374, 0.268378, 0.6057457, 0.68691206, 0.6300343,
-0.79447806, 0.28393722, 0.80315155, 0.73411053, 0.9703951, 0.5488671, 0.18614037, 0.6277461, 0.12960654, 0.33747572,
-0.4241927, 0.6981348, 0.29250467, 0.43891907, 0.8675046, 0.037513115, 0.8382665, 0.79800886, 0.20032, 0.011894401,
-0.3612004, 0.207346, 0.6260507, 0.88860387, 0.27068847, 0.25823146, 0.62024146, 0.72406495, 0.6376153, 0.0719044,
-0.09152406, 0.82603306, 0.9561607, 0.20438583, 0.5442921, 0.4847211, 0.95367795, 0.54303896, 0.3976961, 0.45646,
-0.49825326, 0.3672042, 0.9718153, 0.81778973, 0.73514366, 0.24000394, 0.8482301, 0.43974596, 0.006449677, 0.036392592,
-0.62204725, 0.47036913, 0.4054257, 0.67501765, 0.26883397, 0.58713204, 0.6578865, 0.91454774, 0.46342203, 0.7121636,
-0.92862564, 0.46207544, 0.9901308, 0.057702154, 0.24595165, 0.5981596, 0.74197406, 0.08811883, 0.894627, 0.38278353,
-0.08383514, 0.2952275, 0.40031275, 0.74386, 0.5136412, 0.9939962, 0.2355307, 0.808261, 0.15346022, 0.030684536,
-0.41000134, 0.1804955, 0.71761525, 0.6012227, 0.44985715, 0.6211549, 0.4206074, 0.28114304, 0.9355519, 0.95716006,
-0.82683456, 0.03913026, 0.07961693, 0.6855325, 0.52783436, 0.036177807, 0.3770734, 0.91411316, 0.5718381, 0.13698402,
-0.4980299, 0.76011133, 0.545119, 0.62366617, 0.95255744, 0.32681978, 0.07005637, 0.66156566, 0.16137652, 0.27483776,
-0.35160136, 0.8496255, 0.7610875, 0.4327375, 0.30216226, 0.74813014, 0.74446017, 0.38890806, 0.607845, 0.62479675,
-0.17755221, 0.46083102, 0.15256695, 0.9374669, 0.5559489, 0.04470488, 0.21561056, 0.7147803, 0.21602567, 0.47746333,
-0.6169228, 0.32141757, 0.23642296, 0.016476203, 0.53265464, 0.64989, 0.6353765, 0.0939491, 0.64866525, 0.12303737,
-0.5510985, 0.7590417, 0.11976651, 0.6607141, 0.6055587, 0.9772091, 0.27804276, 0.64687943, 0.38337022, 0.7797042,
-0.29171762, 0.9881654, 0.30626813, 0.94704133, 0.9594318, 0.037198868, 0.60754436, 0.60765207, 0.06771721, 0.9078526,
-0.1112092, 0.3552761, 0.44554, 0.6839132, 0.657915, 0.030183792, 0.6132026, 0.74461126, 0.9000829, 0.6522722,
-0.112753615, 0.6505111, 0.74024284, 0.48480767, 0.073698185, 0.4185105, 0.3410645, 0.49185285, 0.33190826, 0.5787399,
-0.7666621, 0.5687311, 0.33141005, 0.43632144, 0.18574573, 0.6287574, 0.01514944, 0.28938162, 0.057044394, 0.49545577,
-0.042345677, 0.027724478, 0.026231889, 0.74081266, 0.011828165, 0.19582245, 0.31350172, 0.43585333, 0.0027991086, 0.5753749,
-0.36400652, 0.5334315, 0.74679655, 0.731098, 0.6669506, 0.6412065, 0.24792254, 0.8214605, 0.8733431, 0.54092133,
-0.6961343, 0.115691505, 0.27574378, 0.48897734, 0.14119047, 0.5424781, 0.02386607, 0.009218562, 0.49816743, 0.029157575,
-0.015034353, 0.32382092, 0.6875669, 0.40462708, 0.6099266, 0.08502913, 0.6242792, 0.9994301, 0.4729795, 0.87787575,
-0.10500878, 0.90521115, 0.48905376, 0.7565334, 0.21473333, 0.23323065, 0.8219346, 0.60031205, 0.76937085, 0.5445392,
-0.38083488, 0.19368897, 0.41603848, 0.51612306, 0.7993214, 0.92665416, 0.75198066, 0.5372545, 0.5996222, 0.4693501,
-0.17195638, 0.30428314, 0.9376859, 0.9736415, 0.5603405, 0.040185597, 0.8458646, 0.34216946, 0.12117143, 0.58192146,
-0.016927328, 0.24849239, 0.34848097, 0.99546736, 0.43591255, 0.7909232, 0.62663776, 0.51921046, 0.274244, 0.9079598,
-0.72054344, 0.42355403, 0.2398477, 0.95362824, 0.6483227, 0.8213454, 0.90778244, 0.17144382, 0.6053057, 0.68327236,
-0.33304846, 0.08702466, 0.39980793, 0.0036293846, 0.7059194, 0.80072564, 0.96752524, 0.5154122, 0.19619283, 0.17454775,
-0.38736606, 0.47976512, 0.4791406, 0.1874494, 0.52761185, 0.13234249, 0.845208, 0.4205711, 0.08021053, 0.00839825,
-0.3000164, 0.23277025, 0.26301053, 0.6916624, 0.74880666, 0.74840236, 0.064435445, 0.98405766, 0.32531884, 0.73899513,
-0.13240317, 0.6744208, 0.7368638, 0.43789902, 0.24887301, 0.9299027, 0.8486845, 0.34485158, 0.289548, 0.6351869,
-0.82339793, 0.11122555, 0.3230176, 0.09969627, 0.52059376, 0.24077836, 0.9444134, 0.05239831, 0.42601636, 0.5159802,
-0.9761374, 0.48721132, 0.09123329, 0.59690744, 0.383256, 0.1002782, 0.8240141, 0.70814556, 0.25482276, 0.957517,
-0.7362902, 0.9834676, 0.19009337, 0.45719767, 0.042144574, 0.71294534, 0.7429013, 0.041241586, 0.9385764, 0.59770924,
-0.28365803, 0.50035644, 0.13102308, 0.44502363, 0.18500035, 0.18879086, 0.90975267, 0.16331425, 0.17106864, 0.50802827,
-0.80398893, 0.012037134, 0.55804133, 0.8093386, 0.7628578, 0.64519185, 0.58318746, 0.1399564, 0.05464305, 0.14859481,
-0.10588853, 0.14053893, 0.09002884, 0.332031, 0.89889675, 0.8399303, 0.9211322, 0.86581993, 0.057551697, 0.8076484,
-0.49787706, 0.90317184, 0.113821924, 0.82830715, 0.23232217, 0.47578096, 0.35618824, 0.64620966, 0.41190708, 0.19446513,
-0.19052555, 0.6606999, 0.5370769, 0.74679446, 0.15352806, 0.72425306, 0.42542627, 0.3807547, 0.6943399, 0.39695272,
-0.12975785, 0.6029449, 0.98659855, 0.78998154, 0.4918207, 0.1431191, 0.41032755, 0.7989921, 0.5461269, 0.34507003,
-0.26765865, 0.043932725, 0.105762556, 0.36342022, 0.010151213, 0.90081716, 0.89821523, 0.7297342, 0.5770165, 0.2870768,
-0.28900358, 0.9369778, 0.72804934, 0.86017793, 0.95806926, 0.44518864, 0.60346204, 0.34323436, 0.17850293, 0.17464367,
-0.41450405, 0.5403775, 0.17148003, 0.660599, 0.6778906, 0.89493215, 0.9165733, 0.32384035, 0.33648646, 0.08920308,
-0.06545341, 0.5571962, 0.10008278, 0.06683705, 0.92680645, 0.14659283, 0.5549373, 0.17365667, 0.73664325, 0.25271094,
-0.8260378, 0.69569206, 0.80373824, 0.4072631, 0.10794914, 0.19278006, 0.8748956, 0.12642062, 0.8319123, 0.04663203,
-0.53965706, 0.06709321, 0.6204891, 0.37148324, 0.93056595, 0.7272812, 0.8724527, 0.44516358, 0.68552965, 0.11521906,
-0.98424387, 0.57437485, 0.39324772, 0.48781338, 0.22162339, 0.7318074, 0.836895, 0.66121227, 0.9333714, 0.81147647,
-0.89025134, 0.42980537, 0.6065911, 0.925792, 0.3486058, 0.718812, 0.7366392, 0.7642169, 0.55264986, 0.4851105,
-0.02003657, 0.79015267, 0.49192804, 0.28985444, 0.54954606, 0.9983602, 0.936707, 0.72859955, 0.13627109, 0.1995253,
-0.27414012, 0.10977373, 0.48812705, 0.6214242, 0.26846707, 0.251663, 0.30244434, 0.31592485, 0.18563971, 0.3761417,
-0.35588506, 0.2136833, 0.19304918, 0.020435851, 0.1563807, 0.10985168, 0.46050212, 0.69469714, 0.022877397, 0.211754,
-0.99064195, 0.10823577, 0.89251375, 0.20041913, 0.09518249, 0.19409119, 0.082446806, 0.1033933, 0.93826735, 0.22326319,
-0.7951004, 0.108295456, 0.5249412, 0.7338461, 0.53733635, 0.7804776, 0.94167835, 0.9851669, 0.6573249, 0.09694284,
-0.41636762, 0.42071435, 0.5785772, 0.17650813, 0.12922545, 0.8063533, 0.5971035, 0.4714922, 0.13347372, 0.43969434,
-0.53785807, 0.2420099, 0.70572215, 0.9245171, 0.20888333, 0.16590436, 0.21725997, 0.2877079, 0.5262417, 0.07437589,
-0.16921617, 0.19905105, 0.3776575, 0.96237653, 0.58104134, 0.2475896, 0.6887421, 0.459203, 0.48309952, 0.3759031,
-0.16817336, 0.47533524, 0.037372224, 0.92593455, 0.7953864, 0.5699276, 0.52965856, 0.7160056, 0.07119369, 0.28882924,
-0.5969877, 0.6109546, 0.96991956, 0.498573, 0.68540514, 0.5530905, 0.40257332, 0.6004241, 0.52496284, 0.37143198,
-0.56321764, 0.6539704, 0.45892516, 0.58294904, 0.9277267, 0.21731657, 0.043056846, 0.6162007, 0.5954668, 0.88163584,
-0.11761114, 0.13790047, 0.98839265, 0.7575706, 0.271521, 0.06252285, 0.20463766, 0.7797876, 0.1291307, 0.6389557,
-0.6362458, 0.5012543, 0.21651421, 0.23741248, 0.4773882, 0.5582616, 0.22913149, 0.8790845, 0.27697143, 0.02795082,
-0.8450163, 0.08831802, 0.9342402, 0.11166756, 0.8126855, 0.51420295, 0.016410068, 0.4544232, 0.99820787, 0.5780698,
-0.5268707, 0.9134579, 0.12053883, 0.18955784, 0.1712181, 0.45908722, 0.62256193, 0.21234894, 0.227052, 0.62288225,
-0.34845284, 0.6227857, 0.4712934, 0.8860071, 0.73518616, 0.06196327, 0.4374562, 0.22151268, 0.10556084, 0.3694651,
-0.9881851, 0.16397232, 0.3392293, 0.56751597, 0.036619555, 0.029293122, 0.20366028, 0.87672514, 0.94488513, 0.757318,
-0.04611278, 0.75021446, 0.78157973, 0.5510609, 0.112084985, 0.7227879, 0.38071552, 0.026956385, 0.0661944, 0.01830097,
-0.93569964, 0.016782548, 0.6520325, 0.65408915, 0.67949796, 0.22223058, 0.6170246, 0.048233118, 0.37648138, 0.7507222,
-0.07674675, 0.7948974, 0.34886235, 0.6287428, 0.5898847, 0.36289844, 0.5742286, 0.55302286, 0.15293828, 0.14192496,
-0.25542694, 0.74583685, 0.26746377, 0.46973395, 0.5767695, 0.59823835, 0.841206, 0.9202325, 0.7739221, 0.012398226,
-0.6812478, 0.4104998, 0.15531828, 0.087259874, 0.43376547, 0.9714025, 0.5119398, 0.68514013, 0.888018, 0.814389,
-0.4122685, 0.15542716, 0.5002437, 0.19416295, 0.6805713, 0.2512154, 0.4013521, 0.15283692, 0.96117616, 0.7491866,
-0.14855935, 0.8276927, 0.8740181, 0.92426944, 0.762874, 0.18986279, 0.7493188, 0.18229857, 0.07731968, 0.08125962,
-0.3810246, 0.6967921, 0.27431104, 0.36408317, 0.06947445, 0.66624695, 0.6395791, 0.2616025, 0.19497731, 0.6184822,
-0.85095865, 0.88908845, 0.66500485, 0.33854932, 0.72965646, 0.099999785, 0.24559312, 0.07330083, 0.78916264, 0.32555407,
-0.19688624, 0.6883691, 0.9590563, 0.024735536, 0.86383885, 0.8535551, 0.53648174, 0.23104885, 0.32438585, 0.24390268,
-0.22208378, 0.32964125, 0.60782045, 0.8067584, 0.4333644, 0.71547633, 0.88111615, 0.13616055, 0.1246885, 0.014324361,
-0.6116363, 0.13974965, 0.9578596, 0.34269398, 0.89822793, 0.25947088, 0.16268782, 0.53546876, 0.19461296, 0.6628742,
-0.94426966, 0.67601794, 0.3931359, 0.7517656, 0.88437337, 0.6926555, 0.7377358, 0.2495755, 0.50024426, 0.21591938,
-0.12976523, 0.40853027, 0.93721664, 0.95107466, 0.39639843, 0.52131736, 0.28126806, 0.85824645, 0.9051849, 0.01418011,
-0.21888365, 0.10943257, 0.94861233, 0.77483827, 0.7139178, 0.057136595, 0.73050946, 0.61636233, 0.1265076, 0.60436803,
-0.69086725, 0.0010129241, 0.036435887, 0.6615116, 0.299633, 0.54606587, 0.9365053, 0.85605484, 0.922385, 0.7407089,
-0.9777405, 0.63154066, 0.63591623, 0.90876913, 0.88455915, 0.20310602, 0.20253302, 0.0067849625, 0.94629556, 0.37691054,
-0.9782028, 0.30444136, 0.63028383, 0.18043286, 0.4439906, 0.8348371, 0.7274056, 0.61829764, 0.037847787, 0.8272368,
-0.96214604, 0.12137349, 0.123067886, 0.8958763, 0.52505213, 0.1287523, 0.3720944, 0.275705, 0.65144163, 0.85033256,
-0.58481205, 0.42521322, 0.93586147, 0.16447607, 0.036439568, 0.58734304, 0.47351632, 0.039843205, 0.8902792, 0.5108118,
-0.8546036, 0.72372454, 0.6700668, 0.7495971, 0.6261652, 0.3864259, 0.3707291, 0.85600305, 0.21752104, 0.4647959,
-0.81866026, 0.3182077, 0.818207, 0.09514821, 0.77856284, 0.85636705, 0.50847274, 0.74004, 0.38371703, 0.7558068,
-0.83101165, 0.926828, 0.35534334, 0.09596299, 0.7920985, 0.5529896, 0.36857986, 0.46580777, 0.14399329, 0.85664755,
-0.3613208, 0.6875624, 0.72801846, 0.527036, 0.9726332, 0.23842148, 0.45130673, 0.37347084, 0.26971108, 0.1386262,
-0.7580232, 0.51609135, 0.058183976, 0.18664573, 0.031672336, 0.26660433, 0.6070062, 0.84071326, 0.38591322, 0.18007252,
-0.07887025, 0.73347634, 0.6561262, 0.13447234, 0.67980015, 0.92777556, 0.3683812, 0.5741038, 0.95749855, 0.07317559,
-0.017846042, 0.9049213, 0.7120097, 0.36087346, 0.10347511, 0.13109785, 0.5901893, 0.29117107, 0.12251501, 0.54014134,
-0.40506032, 0.13500193, 0.4703289, 0.24509083, 0.9977836, 0.3149203, 0.868644, 0.16869761, 0.06429065, 0.52549416,
-0.94598347, 0.5278666, 0.079894565, 0.9639208, 0.7777773, 0.62784445, 0.0314362, 0.5935461, 0.8472358, 0.04485763,
-0.8700403, 0.8772029, 0.4159723, 0.1965355, 0.120780155, 0.8531019, 0.80408156, 0.6973105, 0.08317062, 0.9005745,
-0.6764151, 0.3158351, 0.71819824, 0.84577185, 0.7750122, 0.94386834, 0.26314744, 0.41103536, 0.13668874, 0.36487988,
-0.059131548, 0.19968359, 0.50981313, 0.4320044, 0.12719214, 0.48997945, 0.82502675, 0.74808896, 0.58309615, 0.47563064,
-0.09966165, 0.9966431, 0.44393525, 0.07765738, 0.67010105, 0.5278574, 0.71902966, 0.27379337, 0.12431067, 0.14468168,
-0.5108387, 0.1713335, 0.08552699, 0.16371617, 0.8490791, 0.63014835, 0.80966836, 0.23412272, 0.18890859, 0.833909,
-0.364697, 0.62040085, 0.45685738, 0.48235595, 0.98572606, 0.6703567, 0.3673898, 0.9839679, 0.06934336, 0.6308007,
-0.02807519, 0.0559926, 0.11421437, 0.60753995, 0.80091286, 0.67977196, 0.87189984, 0.6405409, 0.17567077, 0.24715477,
-0.22483869, 0.9893541, 0.2867247, 0.9920071, 0.85404116, 0.887798, 0.114156604, 0.34609696, 0.5829253, 0.49704382,
-0.6803111, 0.590904, 0.5591804, 0.7491872, 0.110933654, 0.4792608, 0.53978574, 0.9615793, 0.091931306, 0.99974436,
-0.1604676, 0.73506176, 0.20445003, 0.49350995, 0.11660648, 0.4548461, 0.057119142, 0.47798702, 0.36280334, 0.16930713,
-0.7582485, 0.16912746, 0.058451943, 0.9417538, 0.6090703, 0.37534294, 0.33367616, 0.4648503, 0.6283148, 0.09792804,
-0.5562001, 0.021292835, 0.40104258, 0.57229954, 0.95048964, 0.4371712, 0.49681222, 0.36502722, 0.49660632, 0.32165202,
-0.13998619, 0.9103205, 0.54860955, 0.17592642, 0.086687185, 0.48977694, 0.78490406, 0.79321474, 0.8754006, 0.39919505,
-0.8306789, 0.63616955, 0.98329365, 0.41361818, 0.73879534, 0.5111836, 0.53245205, 0.6174266, 0.14011684, 0.7355907,
-0.14558467, 0.074935436, 0.33326453, 0.99400324, 0.44354424, 0.13917476, 0.33401918, 0.6321505, 0.5430203, 0.6794353,
-0.9580339, 0.69209194, 0.9813807, 0.041151315, 0.029320937, 0.8479279, 0.6205179, 0.8825255, 0.85506666, 0.11929336,
-0.5904389, 0.5404614, 0.58944976, 0.22911972, 0.26724914, 0.92003053, 0.037999198, 0.9874244, 0.83350426, 0.439306,
-0.9047191, 0.87938565, 0.22491038, 0.7610156, 0.17606735, 0.06505076, 0.577056, 0.5546063, 0.7323822, 0.94751245,
-0.15575777, 0.15275358, 0.2501944, 0.19596528, 0.44116116, 0.13858697, 0.65478885, 0.9421423, 0.38429725, 0.89086735,
-0.8906657, 0.64992654, 0.7623599, 0.020823486, 0.14515182, 0.6051233, 0.4854857, 0.10414482, 0.7267541, 0.52351373,
-0.10117556, 0.34659478, 0.7986462, 0.10371433, 0.7747162, 0.078648254, 0.46718153, 0.22036512, 0.86508393, 0.9642702,
-0.27087194, 0.06591158, 0.15014334, 0.9075542, 0.9635356, 0.4376853, 0.290267, 0.39348447, 0.78795856, 0.12866218,
-0.26524165, 0.095856875, 0.6031271, 0.94263685, 0.54864025, 0.25479257, 0.11702571, 0.20408688, 0.6158638, 0.5709441,
-0.57956505, 0.47291118, 0.8278522, 0.20886846, 0.8463369, 0.809163, 0.35410735, 0.14648008, 0.4212491, 0.36251292,
-0.67140543, 0.43442374, 0.07705836, 0.42002708, 0.6199954, 0.8247542, 0.4997832, 0.8548057, 0.057287898, 0.7074665,
-0.31485626, 0.09200123, 0.31618625, 0.59809196, 0.25827205, 0.0053186826, 0.7434676, 0.85600936, 0.5550741, 0.5199236,
-0.96162254, 0.26309466, 0.60450137, 0.29413986, 0.38470513, 0.79796076, 0.23805939, 0.9412749, 0.061217327, 0.15437259,
-0.083577976, 0.14378692, 0.9722354, 0.42544565, 0.45725676, 0.8308179, 0.018798511, 0.18310007, 0.32264143, 0.72388613,
-0.75500935, 0.26221997, 0.146799, 0.90839726, 0.25608784, 0.48756382, 0.15672493, 0.22976026, 0.9505964, 0.8410182,
-0.06569535, 0.498098, 0.591406, 0.90132546, 0.40089035, 0.40831077, 0.82992244, 0.7829185, 0.03532195, 0.8220347,
-0.5866948, 0.55850834, 0.7935884, 0.9029153, 0.62388855, 0.17106935, 0.11976584, 0.8907406, 0.14083518, 0.42745417,
-0.9865202, 0.5603676, 0.53336793, 0.83118796, 0.7649143, 0.6994026, 0.116295666, 0.69610405, 0.03805204, 0.8971413,
-0.6412358, 0.008299126, 0.9906785, 0.22019914, 0.08867724, 0.58548, 0.5523809, 0.07090994, 0.024555296, 0.048945986,
-0.0008954834, 0.23588002, 0.14777812, 0.5006067, 0.13719136, 0.19650105, 0.46863157, 0.24388368, 0.28450873, 0.08501847,
-0.367798, 0.26598433, 0.08892508, 0.5231422, 0.854498, 0.50532776, 0.96473, 0.760218, 0.13641119, 0.7014878,
-0.2920151, 0.13381833, 0.74486643, 0.13818067, 0.18079887, 0.57839566, 0.56782985, 0.5733893, 0.8142381, 0.038408525,
-0.61868846, 0.048855904, 0.8661853, 0.091889195, 0.42655867, 0.75064015, 0.41258946, 0.0327612, 0.6939966, 0.5684132,
-0.230771, 0.87241197, 0.41159534, 0.95303357, 0.5293433, 0.37525147, 0.91937405, 0.46753627, 0.3657011, 0.58334947,
-0.62074995, 0.79216284, 0.9344987, 0.32306752, 0.7569309, 0.8670772, 0.49101356, 0.0095974505, 0.31980786, 0.5587957,
-0.6286712, 0.8952423, 0.42964563, 0.24610022, 0.46633002, 0.31894207, 0.39979902, 0.99703586, 0.09658354, 0.10385787,
-0.092738345, 0.9319688, 0.066221446, 0.567998, 0.47071677, 0.41960314, 0.722223, 0.79183286, 0.60883737, 0.8055474,
-0.6590216, 0.10029357, 0.20768817, 0.2308886, 0.41765857, 0.82652557, 0.11435715, 0.5431178, 0.3349583, 0.55948156,
-0.2596266, 0.402992, 0.7129533, 0.13520089, 0.939742, 0.33552873, 0.44276634, 0.16549513, 0.48670354, 0.2104012,
-0.9754525, 0.9223382, 0.37095273, 0.26184326, 0.4906111, 0.68878114, 0.7259414, 0.3665008, 0.8523507, 0.33732775,
-0.14485414, 0.69918066, 0.40076008, 0.5142605, 0.89977413, 0.52837765, 0.6875541, 0.19875702, 0.8284416, 0.6398044,
-0.20458493, 0.8566812, 0.66207755, 0.537102, 0.84423125, 0.6897463, 0.2190155, 0.93102056, 0.62825596, 0.13518804,
-0.9768368, 0.5567279, 0.30512935, 0.39843616, 0.83009493, 0.7366834, 0.72934085, 0.9458449, 0.7402775, 0.7288774,
-0.100584194, 0.7478564, 0.69076705, 0.99763054, 0.41462737, 0.5604459, 0.002231921, 0.19869287, 0.23542677, 0.41136438,
-0.6479746, 0.24400933, 0.33705348, 0.8468991, 0.0058162767, 0.11877123, 0.26026058, 0.83385074, 0.417612, 0.80086476,
-0.46976563, 0.79492086, 0.73824483, 0.71716267, 0.36049098, 0.58812624, 0.3940513, 0.0023239073, 0.68416554, 0.1630907,
-0.7990368, 0.74170923, 0.45847952, 0.0995642, 0.5392202, 0.45672858, 0.16591415, 0.664447, 0.12247461, 0.28378534,
-0.6875144, 0.020322617, 0.6955938, 0.21689159, 0.48721343, 0.7328274, 0.21967441, 0.45823023, 0.39261988, 0.7113237,
-0.47642282, 0.8954901, 0.52823293, 0.9394127, 0.25911182, 0.30566335, 0.009611528, 0.9736044, 0.63713956, 0.82650113,
-0.16639459, 0.99990803, 0.5145273, 0.07233607, 0.6123276, 0.9062654, 0.7855298, 0.23748927, 0.30767888, 0.5490877,
-0.9528571, 0.5958136, 0.71137613, 0.13382663, 0.11335034, 0.449443, 0.09932706, 0.52135324, 0.22994924, 0.6276635,
-0.36845186, 0.93582106, 0.609704, 0.9728418, 0.68666786, 0.9035467, 0.21347627, 0.51906675, 0.8404524, 0.2335569,
-0.44711703, 0.19230975, 0.027307436, 0.29597348, 0.11739075, 0.6876064, 0.5057953, 0.6232577, 0.604564, 0.58094805,
-0.94729763, 0.9821851, 0.15055138, 0.8435322, 0.7584666, 0.8806093, 0.18411398, 0.3944063, 0.8260624, 0.8096688,
-0.20633629, 0.48825827, 0.74365515, 0.009476059, 0.45804924, 0.23057352, 0.39020398, 0.5416855, 0.3856682, 0.7087808,
-0.69278914, 0.26646304, 0.39703688, 0.074121974, 0.10197067, 0.76054734, 0.5685061, 0.41540262, 0.016435882, 0.42574394,
-0.94364774, 0.47606933, 0.91678923, 0.6490012, 0.68036586, 0.38626674, 0.78526974, 0.7661718, 0.2143752, 0.80605865,
-0.7194327, 0.81907, 0.69300437, 0.030783592, 0.027220597, 0.9588587, 0.4486546, 0.017831376, 0.83792424, 0.8868172,
-0.2974024, 0.9641097, 0.23758952, 0.8957832, 0.8881589, 0.6808346, 0.5851483, 0.0764294, 0.74156153, 0.9979193,
-0.3121031, 0.7687113, 0.37797043, 0.40031847, 0.86602104, 0.730267, 0.57146907, 0.094653964, 0.32911018, 0.07178252,
-0.4453038, 0.62403214, 0.32731032, 0.5796096, 0.9893481, 0.87371916, 0.5734587, 0.3662533, 0.046901383, 0.14311191,
-0.31189272, 0.5506748, 0.5774784, 0.12961864, 0.12834151, 0.97953796, 0.23847981, 0.021006035, 0.76084226, 0.99953127,
-0.8011185, 0.7088403, 0.024610326, 0.21645589, 0.49395552, 0.9507214, 0.44109955, 0.2926859, 0.16476253, 0.29695365,
-0.3873897, 0.35400063, 0.6887212, 0.7661417, 0.44151342, 0.67337024, 0.6367994, 0.65797997, 0.906435, 0.014439769,
-0.10737592, 0.21889497, 0.029528014, 0.5984496, 0.6860266, 0.76142836, 0.19123298, 0.24835177, 0.27197698, 0.8864831,
-0.49178717, 0.550463, 0.3338117, 0.32957888, 0.27066407, 0.7364635, 0.59942186, 0.11085444, 0.08565405, 0.03862678,
-0.4326196, 0.28077278, 0.20149076, 0.7499477, 0.7557222, 0.95789206, 0.86195356, 0.8113367, 0.6881052, 0.45497125,
-0.34273857, 0.5804998, 0.11457099, 0.7464025, 0.8921554, 0.5822235, 0.6793123, 0.42616072, 0.5304293, 0.7325272,
-0.7594884, 0.19274779, 0.02070892, 0.27827948, 0.8051665, 0.83692664, 0.020188946, 0.35914233, 0.49547768, 0.70504993,
-0.07394841, 0.525945, 0.5723259, 0.8678083, 0.5818202, 0.8266031, 0.017404223, 0.27958027, 0.84272736, 0.7281345,
-0.8994748, 0.3798963, 0.5602465, 0.8170057, 0.5437445, 0.9112873, 0.43589205, 0.5874092, 0.4374235, 0.68844056,
-0.057151183, 0.1732611, 0.58042514, 0.35312688, 0.2791384, 0.23987181, 0.26006386, 0.9232113, 0.94478124, 0.9187956,
-0.93770313, 0.50281125, 0.31585902, 0.9830553, 0.38102284, 0.8167936, 0.008173941, 0.24676272, 0.16458233, 0.06555225,
-0.5648193, 0.39973202, 0.58343333, 0.8022948, 0.8330524, 0.3795921, 0.63250124, 0.20370321, 0.734535, 0.8938792,
-0.40103462, 0.43277976, 0.92171884, 0.8070371, 0.64789873, 0.9006873, 0.94551986, 0.21919903, 0.5886699, 0.34194836,
-0.5665393, 0.09419294, 0.33479902, 0.92393184, 0.7904314, 0.39666355, 0.0640373, 0.5771913, 0.43598288, 0.7269509,
-0.90311337, 0.18912931, 0.42282686, 0.37187123, 0.12362129, 0.65741915, 0.5898278, 0.77813035, 0.5200745, 0.8995463,
-0.6073706, 0.056360655, 0.18867631, 0.05090209, 0.51776093, 0.5049234, 0.5810924, 0.5088219, 0.3351565, 0.48033553,
-0.87127376, 0.7889749, 0.65809286, 0.822634, 0.49901298, 0.47062632, 0.064933024, 0.65950155, 0.0118634105, 0.43638885,
-0.3155548, 0.055309944, 0.76772034, 0.007584079, 0.9907658, 0.2119053, 0.0099529, 0.5498476, 0.68341583, 0.9904796,
-0.31085956, 0.16738948, 0.6991246, 0.6891236, 0.7345778, 0.5101786, 0.9055166, 0.28389692, 0.40617087, 0.285508,
-0.8155711, 0.5552154, 0.24203478, 0.95564735, 0.8556771, 0.11413846, 0.53103644, 0.6001929, 0.8728583, 0.652995,
-0.59248614, 0.9303262, 0.76626694, 0.083685614, 0.5839915, 0.55206066, 0.28864032, 0.18109223, 0.06013629, 0.30585563,
-0.49497047, 0.031244803, 0.8254061, 0.34467688, 0.16947599, 0.70388424, 0.089850344, 0.9689693, 0.088056214, 0.9888344,
-0.56510967, 0.7810361, 0.25333068, 0.72635543, 0.6208177, 0.7603394, 0.81327516, 0.812073, 0.15190694, 0.8766273,
-0.68086886, 0.40976003, 0.6769893, 0.03042084, 0.39799348, 0.38053334, 0.40112254, 0.61543894, 0.10513203, 0.18251711,
-0.22153829, 0.7244244, 0.22376063, 0.10031522, 0.79053754, 0.7843263, 0.7298093, 0.8973579, 0.7861713, 0.15179288,
-0.024288114, 0.56206715, 0.51213664, 0.8840239, 0.08788527, 0.81145, 0.6769955, 0.039911535, 0.4628679, 0.82365215,
-0.7387855, 0.47656733, 0.029185295, 0.18350895, 0.62498677, 0.08521046, 0.35425547, 0.7949853, 0.9466834, 0.78894264,
-0.30276173, 0.4744114, 0.86383724, 0.9055391, 0.7672961, 0.8406853, 0.5572755, 0.15301545, 0.9358179, 0.83649135,
-0.030530108, 0.9159173, 0.025901658, 0.00011405395, 0.8523392, 0.1188017, 0.89762336, 0.7929654, 0.9425356, 0.58654344,
-0.7035378, 0.361211, 0.15257105, 0.2814799, 0.44373164, 0.744971, 0.6952391, 0.040251687, 0.47532842, 0.70532703,
-0.43007088, 0.93482405, 0.9506745, 0.9972287, 0.84903115, 0.5498767, 0.6982299, 0.60659754, 0.116727814, 0.24719998,
-0.25417453, 0.5239801, 0.10409364, 0.6263765, 0.79312205, 0.82286817, 0.45066565, 0.02907124, 0.33116972, 0.5061851,
-0.1875871, 0.56129, 0.8524497, 0.36013994, 0.085404865, 0.94155073, 0.32184035, 0.58235735, 0.46180746, 0.022325099,
-0.14544618, 0.5170238, 0.67768705, 0.23049083, 0.4064205, 0.09570609, 0.9652428, 0.028672969, 0.1510829, 0.30246252,
-0.4205718, 0.2910258, 0.67623764, 0.69533557, 0.33236894, 0.17955771, 0.25711736, 0.5261945, 0.48835787};
+static int _rnd_count = 9999;
+static float _rnd[] = {
+ 0.39540747, 0.841546, 0.52073574, 0.80399257, 0.95868486, 0.46164507, 0.5644759, 0.50258803,
+ 0.1953517, 0.40522006, 0.7953865, 0.7795385, 0.6009604, 0.03921096, 0.56872225, 0.93369347,
+ 0.7019503, 0.5392296, 0.2671585, 0.87286836, 0.28110227, 0.41505373, 0.8609184, 0.65234584,
+ 0.18079561, 0.1345461, 0.26905555, 0.97823226, 0.9349287, 0.37662244, 0.47883937, 0.1831086,
+ 0.63446456, 0.2549137, 0.8205819, 0.44705132, 0.7044422, 0.36040744, 0.29616997, 0.60375917,
+ 0.21973382, 0.094351165, 0.3769042, 0.9975177, 0.6133292, 0.3379986, 0.88620085, 0.83456165,
+ 0.16677794, 0.2749627, 0.28938183, 0.6274365, 0.058304083, 0.97233975, 0.48520145, 0.9803537,
+ 0.9806276, 0.8683899, 0.62319696, 0.82413876, 0.19258952, 0.5862436, 0.5676593, 0.8187293,
+ 0.9263807, 0.6122779, 0.14507395, 0.34604672, 0.21862903, 0.121670924, 0.22925124, 0.34154287,
+ 0.2430596, 0.66339934, 0.6531345, 0.1867511, 0.038149532, 0.8634007, 0.039016694, 0.84279704,
+ 0.24834526, 0.4344939, 0.8114543, 0.65996605, 0.08724063, 0.8514029, 0.12480451, 0.6621248,
+ 0.76971227, 0.8402282, 0.46642372, 0.83605236, 0.73721045, 0.47203118, 0.41116965, 0.6334902,
+ 0.52669185, 0.55817497, 0.07113702, 0.0010512439, 0.19292463, 0.5401541, 0.61593264, 0.045107026,
+ 0.04571145, 0.94783896, 0.3843769, 0.39490476, 0.3192052, 0.29845035, 0.9422042, 0.11722695,
+ 0.8293732, 0.7804, 0.5757935, 0.7580956, 0.7747893, 0.90769327, 0.73148865, 0.074977815,
+ 0.4874734, 0.48294914, 0.5763345, 0.37840083, 0.6552472, 0.39319888, 0.6043324, 0.77102846,
+ 0.25222966, 0.019644327, 0.6600592, 0.4799746, 0.7922636, 0.03796545, 0.64987236, 0.70819116,
+ 0.81856126, 0.7663473, 0.6142546, 0.13940167, 0.46702597, 0.72989976, 0.34291962, 0.47126192,
+ 0.89802396, 0.34919676, 0.0066791615, 0.95681053, 0.8962376, 0.653074, 0.85870093, 0.6189986,
+ 0.8266863, 0.9961592, 0.5135778, 0.7099755, 0.9638197, 0.2375318, 0.3898598, 0.65251255,
+ 0.34350657, 0.6133485, 0.14267509, 0.29956087, 0.6383911, 0.4622296, 0.3249633, 0.79140776,
+ 0.13052759, 0.8676024, 0.93953437, 0.008441999, 0.2934387, 0.592087, 0.6079518, 0.75757366,
+ 0.14002953, 0.10507256, 0.48037684, 0.30605045, 0.38651973, 0.64752185, 0.8747908, 0.59915566,
+ 0.1609434, 0.04106063, 0.65328825, 0.79610443, 0.5243876, 0.9398969, 0.7443715, 0.5810295,
+ 0.3764875, 0.961742, 0.7958951, 0.8536775, 0.58722466, 0.043358732, 0.8328708, 0.43579438,
+ 0.024233455, 0.21527143, 0.8262829, 0.028635254, 0.71353966, 0.85025895, 0.3255599, 0.23459937,
+ 0.38820738, 0.7560042, 0.569946, 0.8587471, 0.75715494, 0.083809346, 0.26599285, 0.6959847,
+ 0.73855764, 0.54351944, 0.13861747, 0.59733045, 0.80894136, 0.52885884, 0.26702014, 0.1906307,
+ 0.123230904, 0.35850486, 0.6319545, 0.3316967, 0.7961919, 0.7542743, 0.17034897, 0.0966708,
+ 0.27220175, 0.04458247, 0.28181702, 0.1712483, 0.82123893, 0.8461555, 0.88561594, 0.3106845,
+ 0.7155007, 0.4186889, 0.40789708, 0.76838344, 0.36995092, 0.8856244, 0.82387453, 0.29267815,
+ 0.69574916, 0.099910386, 0.11511985, 0.04370523, 0.9047413, 0.23554033, 0.62685305, 0.4953746,
+ 0.9482513, 0.63565224, 0.9054043, 0.3550348, 0.21830441, 0.9938632, 0.4384075, 0.633933,
+ 0.5856552, 0.47327515, 0.58654535, 0.71257246, 0.80199236, 0.09474454, 0.8747458, 0.8924021,
+ 0.6579035, 0.82793295, 0.88182974, 0.39025244, 0.12096177, 0.4986367, 0.8206798, 0.23760653,
+ 0.53463036, 0.33927637, 0.6359475, 0.6962815, 0.6391545, 0.12664375, 0.19192953, 0.036661416,
+ 0.41772944, 0.7864424, 0.222997, 0.18558672, 0.9407512, 0.5305812, 0.092380084, 0.7216375,
+ 0.9802814, 0.77396405, 0.18272822, 0.89667577, 0.29907903, 0.11130205, 0.4906858, 0.60100466,
+ 0.22516462, 0.22271773, 0.38580173, 0.07680829, 0.3537106, 0.23660058, 0.37441283, 0.4496146,
+ 0.81497246, 0.6677978, 0.82040447, 0.879028, 0.35791573, 0.742126, 0.9947786, 0.45901147,
+ 0.28134564, 0.54988396, 0.29484302, 0.015549939, 0.87174755, 0.68915904, 0.9516509, 0.12732233,
+ 0.7355529, 0.16019227, 0.40997103, 0.34699774, 0.31590846, 0.924004, 0.93852746, 0.4233283,
+ 0.84859055, 0.034942873, 0.47111684, 0.41643673, 0.740842, 0.115121245, 0.68295085, 0.18112887,
+ 0.41202956, 0.77338237, 0.3706143, 0.27295336, 0.7101767, 0.21335205, 0.36372176, 0.2381554,
+ 0.7791855, 0.72371674, 0.6153301, 0.7491951, 0.816459, 0.47513586, 0.7292571, 0.5360056,
+ 0.2710668, 0.25847942, 0.3412554, 0.19351831, 0.8266295, 0.0274151, 0.13370614, 0.8909684,
+ 0.72927034, 0.39707616, 0.030437447, 0.32297286, 0.27100918, 0.57834184, 0.71816945, 0.16622439,
+ 0.8669331, 0.11371415, 0.6035204, 0.09836516, 0.31854475, 0.6786976, 0.41714564, 0.5222008,
+ 0.7964705, 0.17181565, 0.56781226, 0.5921917, 0.30867395, 0.1893324, 0.6068693, 0.37345472,
+ 0.3056858, 0.9351113, 0.14536993, 0.4823626, 0.7738658, 0.4894325, 0.35449934, 0.38461447,
+ 0.6396763, 0.4796459, 0.54368305, 0.31310055, 0.18291461, 0.040748898, 0.9671462, 0.20084366,
+ 0.0055472897, 0.4491057, 0.882262, 0.7027449, 0.87161547, 0.6308919, 0.21746083, 0.59236926,
+ 0.8413338, 0.81905454, 0.3970478, 0.6548139, 0.45960286, 0.5415144, 0.58229446, 0.539938,
+ 0.7902069, 0.6569827, 0.017287076, 0.33589792, 0.4329719, 0.23580688, 0.39235854, 0.3775006,
+ 0.7592148, 0.2189059, 0.45868888, 0.83889884, 0.13501453, 0.10404509, 0.3392862, 0.7557216,
+ 0.20466943, 0.36696857, 0.5866444, 0.85956824, 0.3070704, 0.9041244, 0.5018392, 0.67479384,
+ 0.7176504, 0.5530007, 0.6410288, 0.9548113, 0.092384726, 0.69968545, 0.92501163, 0.09816185,
+ 0.89735144, 0.0037450776, 0.52289367, 0.5259319, 0.023461822, 0.6312483, 0.7678718, 0.7697404,
+ 0.05674718, 0.5047614, 0.9435301, 0.6527096, 0.17220303, 0.37856197, 0.45735472, 0.7372887,
+ 0.47976837, 0.6413262, 0.45014447, 0.09263428, 0.95487, 0.7227262, 0.23286755, 0.8860825,
+ 0.15514348, 0.34249324, 0.61824745, 0.8799712, 0.59477806, 0.43754727, 0.28511587, 0.059529364,
+ 0.2938943, 0.36052704, 0.9415474, 0.13126945, 0.5811514, 0.8133543, 0.7322598, 0.5734211,
+ 0.5990968, 0.816904, 0.80282104, 0.802309, 0.96059436, 0.8491296, 0.50259084, 0.33908847,
+ 0.09564596, 0.9037401, 0.4750429, 0.45105854, 0.24954097, 0.8323773, 0.14329186, 0.17462522,
+ 0.77087754, 0.63681114, 0.3707884, 0.6809686, 0.013000839, 0.8879006, 0.17496233, 0.61919993,
+ 0.21964556, 0.8840007, 0.3588153, 0.81167597, 0.43701455, 0.32608527, 0.15613726, 0.666414,
+ 0.9090664, 0.87672335, 0.4935375, 0.13796596, 0.9199052, 0.43055856, 0.9254882, 0.30601385,
+ 0.8399024, 0.279159, 0.78432524, 0.69103795, 0.9625043, 0.83405733, 0.8099884, 0.46151695,
+ 0.2172352, 0.7669222, 0.3603919, 0.9443403, 0.44256592, 0.0512912, 0.5604203, 0.7111962,
+ 0.64194167, 0.18362112, 0.5826634, 0.07659364, 0.49031433, 0.6909148, 0.9020739, 0.7695607,
+ 0.7476028, 0.80862886, 0.5419922, 0.3728176, 0.33883983, 0.005325912, 0.25472003, 0.34031895,
+ 0.711323, 0.064774565, 0.8410662, 0.73384184, 0.10357534, 0.48392436, 0.65669554, 0.38558826,
+ 0.07401231, 0.8972984, 0.5944408, 0.67009234, 0.96569335, 0.21179698, 0.22384812, 0.8577752,
+ 0.31630307, 0.7823413, 0.49602425, 0.7362841, 0.84789515, 0.84889454, 0.8156995, 0.14898759,
+ 0.3770851, 0.01476456, 0.94343513, 0.15387547, 0.29206514, 0.43717077, 0.12267711, 0.21190928,
+ 0.5122022, 0.020072967, 0.23301727, 0.37779135, 0.21022503, 0.82657844, 0.60762084, 0.15801735,
+ 0.52692556, 0.19707517, 0.0025813282, 0.59301597, 0.09647403, 0.23198159, 0.80386734, 0.5358059,
+ 0.58478075, 0.684217, 0.056514528, 0.5564985, 0.50930166, 0.51843596, 0.4924238, 0.8624285,
+ 0.24907504, 0.6920786, 0.35675675, 0.08881078, 0.5404892, 0.5028201, 0.0935231, 0.63684154,
+ 0.77462125, 0.38253152, 0.15789017, 0.94562036, 0.97877973, 0.84605676, 0.64755017, 0.48972467,
+ 0.17472044, 0.3380069, 0.2093585, 0.65081996, 0.8463132, 0.22268358, 0.052513562, 0.1451035,
+ 0.21089722, 0.40762928, 0.5690947, 0.60784817, 0.38065624, 0.56617856, 0.70260763, 0.99376625,
+ 0.52764916, 0.37058878, 0.1287163, 0.51814646, 0.4698217, 0.5188101, 0.61752814, 0.024105478,
+ 0.103552066, 0.3657398, 0.81839466, 0.7139425, 0.07409142, 0.858247, 0.55702615, 0.738724,
+ 0.03666682, 0.56678987, 0.38177812, 0.17129473, 0.30907747, 0.8416038, 0.016115308, 0.02639147,
+ 0.639565, 0.21165326, 0.87791353, 0.13285992, 0.9337254, 0.48567492, 0.2561853, 0.20844269,
+ 0.6799239, 0.16412394, 0.41797122, 0.60819095, 0.71734047, 0.12940371, 0.019902974, 0.6559104,
+ 0.7204788, 0.18525302, 0.5472679, 0.4805734, 0.4042889, 0.33857107, 0.07101207, 0.35265025,
+ 0.85060316, 0.8303707, 0.57118136, 0.8138664, 0.18440045, 0.5313129, 0.68468875, 0.68604535,
+ 0.35447347, 0.10232483, 0.8785814, 0.25816843, 0.6408965, 0.48466823, 0.09038009, 0.6178771,
+ 0.10955451, 0.609952, 0.034018606, 0.9099675, 0.44027576, 0.9488352, 0.021383535, 0.9072631,
+ 0.5468869, 0.72586775, 0.45081598, 0.12382444, 0.29433593, 0.5355419, 0.62210256, 0.30099395,
+ 0.14064118, 0.5252633, 0.28225678, 0.10335469, 0.91449356, 0.44231892, 0.024042243, 0.14861101,
+ 0.47943518, 0.7319259, 0.2537175, 0.6150156, 0.25082228, 0.76173455, 0.01501382, 0.23581055,
+ 0.09487294, 0.9293908, 0.3710189, 0.7943369, 0.30455244, 0.1610446, 0.9123745, 0.90176797,
+ 0.80898714, 0.66391826, 0.2669795, 0.4585327, 0.08049692, 0.5608643, 0.3917094, 0.8189315,
+ 0.48022225, 0.5775875, 0.11752723, 0.11563321, 0.20241146, 0.9870254, 0.70338356, 0.6672356,
+ 0.5859097, 0.88540757, 0.4305323, 0.7083498, 0.69511765, 0.4063679, 0.6564408, 0.7851523,
+ 0.71085393, 0.21500541, 0.028951503, 0.36494514, 0.16452302, 0.8277657, 0.9964415, 0.9795966,
+ 0.6128888, 0.38048878, 0.29436752, 0.25057533, 0.17533945, 0.56550956, 0.06811409, 0.9185709,
+ 0.3402165, 0.43478596, 0.13479339, 0.6732348, 0.64420736, 0.8993806, 0.033399098, 0.10784754,
+ 0.22600721, 0.7037833, 0.20842715, 0.41914487, 0.7305123, 0.20402466, 0.2066503, 0.40261927,
+ 0.007477421, 0.48182714, 0.74767876, 0.8654915, 0.5319128, 0.026764244, 0.6544085, 0.6524566,
+ 0.58114594, 0.13793063, 0.50274444, 0.82192266, 0.6926579, 0.45280823, 0.49189615, 0.020400187,
+ 0.8172935, 0.51196146, 0.36813334, 0.26033172, 0.27157453, 0.983206, 0.140945, 0.81147337,
+ 0.18160632, 0.92110395, 0.13893794, 0.46073973, 0.6193385, 0.5772967, 0.2490843, 0.40886414,
+ 0.1738385, 0.89174825, 0.24309792, 0.6935123, 0.8178308, 0.20262258, 0.38665804, 0.31345224,
+ 0.78037745, 0.48233682, 0.09208888, 0.50627667, 0.3966362, 0.21147643, 0.41518968, 0.77319896,
+ 0.21188715, 0.18802696, 0.60185134, 0.21855086, 0.8358913, 0.94631857, 0.13104475, 0.024271427,
+ 0.34088212, 0.9362054, 0.6838852, 0.61080885, 0.8878263, 0.1936688, 0.03311803, 0.0038492912,
+ 0.88884634, 0.09388026, 0.64808416, 0.8009096, 0.2097103, 0.79838383, 0.20256937, 0.61467093,
+ 0.1253034, 0.054681093, 0.47995427, 0.7892377, 0.8911171, 0.6346683, 0.41483715, 0.9701299,
+ 0.5059143, 0.36573896, 0.24885257, 0.43131158, 0.97544533, 0.03053343, 0.57297283, 0.2275199,
+ 0.7607035, 0.21882649, 0.3526302, 0.8816254, 0.5187374, 0.77584916, 0.42562595, 0.58670866,
+ 0.44921878, 0.08823959, 0.6174303, 0.30275592, 0.5633923, 0.61428005, 0.56348866, 0.41350332,
+ 0.9854576, 0.9871804, 0.093247466, 0.7812102, 0.4663643, 0.34180707, 0.13315432, 0.70621383,
+ 0.52136827, 0.7137553, 0.10489457, 0.52208734, 0.94481623, 0.60180646, 0.028403986, 0.8583129,
+ 0.5209074, 0.42056426, 0.04020609, 0.9908838, 0.44575363, 0.32094392, 0.09593353, 0.34945422,
+ 0.62905514, 0.89324564, 0.3400189, 0.80287755, 0.017237967, 0.112081215, 0.40673763, 0.8916342,
+ 0.80225027, 0.83534926, 0.44585398, 0.98826486, 0.93728596, 0.79176265, 0.7611556, 0.41889647,
+ 0.08567218, 0.64641637, 0.3602572, 0.80498207, 0.6709546, 0.9035386, 0.64189243, 0.84741235,
+ 0.0598356, 0.7591174, 0.7818485, 0.142828, 0.574074, 0.5726049, 0.96774966, 0.6645137,
+ 0.8912469, 0.74379325, 0.15215507, 0.5731187, 0.0017881524, 0.3302768, 0.6889758, 0.40928704,
+ 0.30701768, 0.21326037, 0.71983707, 0.10946698, 0.1559525, 0.040139113, 0.92102695, 0.7291448,
+ 0.6594087, 0.62130964, 0.9052116, 0.79933727, 0.9606867, 0.29095143, 0.6784996, 0.72551656,
+ 0.2513532, 0.49260658, 0.74304193, 0.25812054, 0.33023268, 0.2639096, 0.31756023, 0.22964539,
+ 0.86759955, 0.7813403, 0.097017966, 0.19349271, 0.63960755, 0.18803692, 0.4171083, 0.7553954,
+ 0.95744056, 0.9509702, 0.4979644, 0.45769426, 0.18370152, 0.53242546, 0.69145983, 0.019696489,
+ 0.8380905, 0.052703734, 0.48341933, 0.95276433, 0.6673932, 0.16841243, 0.70382696, 0.6002955,
+ 0.06529366, 0.42663854, 0.32176548, 0.50918156, 0.58723485, 0.4308553, 0.079054326, 0.04310807,
+ 0.89570016, 0.4901917, 0.24186741, 0.3746122, 0.94312114, 0.72753423, 0.08953723, 0.47137174,
+ 0.20420133, 0.14981624, 0.8418967, 0.009716521, 0.79298705, 0.22080535, 0.541815, 0.71892774,
+ 0.80114675, 0.72334546, 0.42003006, 0.27752897, 0.7804903, 0.36479586, 0.56225216, 0.69918716,
+ 0.07751329, 0.4967225, 0.12819904, 0.212969, 0.86627144, 0.90792674, 0.16816054, 0.5265852,
+ 0.8719159, 0.45485634, 0.56199414, 0.6935098, 0.29055804, 0.31684762, 0.07657534, 0.11055623,
+ 0.9631665, 0.012047576, 0.74856305, 0.517577, 0.32651573, 0.69411045, 0.80730844, 0.8444883,
+ 0.88482356, 0.60283774, 0.7080349, 0.8638894, 0.010825248, 0.80152535, 0.26261777, 0.53090423,
+ 0.92793953, 0.54268026, 0.29709893, 0.44639865, 0.5993352, 0.8765682, 0.6051003, 0.2962746,
+ 0.9816557, 0.31531146, 0.13780066, 0.3381307, 0.6588112, 0.84830517, 0.4283697, 0.48429912,
+ 0.6467701, 0.30947384, 0.31436247, 0.7684427, 0.6162329, 0.044675153, 0.3726714, 0.38340282,
+ 0.689414, 0.28371072, 0.32814547, 0.26343372, 0.19989188, 0.30427113, 0.51576, 0.07039049,
+ 0.19223855, 0.031089857, 0.7655703, 0.7478778, 0.019748688, 0.63017666, 0.511221, 0.08659828,
+ 0.40694728, 0.45228842, 0.53592134, 0.011204251, 0.5563098, 0.46917772, 0.18567711, 0.036518365,
+ 0.17446801, 0.22373573, 0.21711932, 0.7013514, 0.48716292, 0.49417505, 0.9146714, 0.88326436,
+ 0.17000887, 0.9136961, 0.7569846, 0.3156245, 0.54842275, 0.34166658, 0.09638273, 0.67738456,
+ 0.7995515, 0.06741016, 0.14589214, 0.62772137, 0.08273488, 0.680492, 0.46455044, 0.016593413,
+ 0.7982528, 0.22776419, 0.36149544, 0.16394442, 0.50875384, 0.36146715, 0.827093, 0.22023632,
+ 0.098033614, 0.2916271, 0.088965714, 0.9761561, 0.08715181, 0.8144086, 0.5832276, 0.6980635,
+ 0.11641844, 0.8823059, 0.5778689, 0.106052585, 0.8731921, 0.19559653, 0.5381755, 0.06528069,
+ 0.3559057, 0.8585367, 0.21165277, 0.48889965, 0.32328558, 0.55795574, 0.95378345, 0.49397606,
+ 0.7591853, 0.20052591, 0.9030986, 0.25939873, 0.13267961, 0.750727, 0.37451053, 0.8085417,
+ 0.086603075, 0.5367483, 0.21759088, 0.25679567, 0.25270087, 0.120226584, 0.59023273, 0.9851429,
+ 0.48418257, 0.44782865, 0.51130295, 0.20042898, 0.102623075, 0.35849786, 0.14340132, 0.6026563,
+ 0.68958867, 0.29621476, 0.8080387, 0.6502171, 0.14981438, 0.3381934, 0.8969507, 0.54007787,
+ 0.33784363, 0.59498966, 0.21697083, 0.8866259, 0.91130996, 0.32382888, 0.5653839, 0.36569145,
+ 0.5077954, 0.76932716, 0.01944951, 0.3364438, 0.97800565, 0.28137985, 0.8125798, 0.2356791,
+ 0.268304, 0.22650987, 0.00471706, 0.8754569, 0.04665282, 0.7533545, 0.39135298, 0.40068746,
+ 0.05712457, 0.3004423, 0.56981003, 0.8364648, 0.9426883, 0.7242934, 0.65872735, 0.7484097,
+ 0.63979757, 0.677513, 0.91895205, 0.6577112, 0.90325576, 0.70360684, 0.07383294, 0.1603537,
+ 0.88244474, 0.14561148, 0.6926336, 0.3332959, 0.33904833, 0.80695754, 0.62465066, 0.40820882,
+ 0.48363495, 0.5723596, 0.38191313, 0.9233045, 0.33347633, 0.021493766, 0.49342504, 0.5844891,
+ 0.20363668, 0.81628335, 0.82950133, 0.6108677, 0.75401884, 0.728919, 0.42300317, 0.7835019,
+ 0.11059984, 0.2710398, 0.6966462, 0.30049264, 0.3624278, 0.1548686, 0.33242336, 0.56469715,
+ 0.15267694, 0.84436333, 0.9930122, 0.9010413, 0.06072089, 0.058057077, 0.061639126, 0.25016704,
+ 0.6757917, 0.16160122, 0.3528299, 0.37032866, 0.34238032, 0.7354228, 0.41493335, 0.6183038,
+ 0.18408795, 0.3344629, 0.45407453, 0.08697238, 0.8741055, 0.46296528, 0.40633488, 0.1535257,
+ 0.7226083, 0.90913165, 0.22269607, 0.068008505, 0.1103113, 0.32415798, 0.045781024, 0.32876635,
+ 0.23993625, 0.817216, 0.77062756, 0.48911297, 0.028481547, 0.5923837, 0.52376825, 0.14557959,
+ 0.7546443, 0.5793343, 0.935076, 0.5924176, 0.37608913, 0.05267449, 0.44112164, 0.37517703,
+ 0.85610646, 0.078342445, 0.11640469, 0.02796489, 0.70079404, 0.24545097, 0.69059163, 0.68971163,
+ 0.43802848, 0.83948654, 0.17843302, 0.15158923, 0.835361, 0.99363065, 0.13985574, 0.3516337,
+ 0.115820184, 0.02406358, 0.13039242, 0.5251643, 0.96479523, 0.92582035, 0.58982223, 0.59170425,
+ 0.8106947, 0.30849496, 0.33232814, 0.2947712, 0.5278893, 0.8139172, 0.77743655, 0.6699338,
+ 0.46801004, 0.84751904, 0.21190204, 0.031968854, 0.2077533, 0.017816134, 0.62797225, 0.99448526,
+ 0.12662433, 0.080915935, 0.05108449, 0.18899502, 0.41395068, 0.372179, 0.3102186, 0.7610136,
+ 0.43947858, 0.5834423, 0.47659743, 0.35202554, 0.9222821, 0.9159573, 0.4103818, 0.9302861,
+ 0.4885202, 0.52470046, 0.21727021, 0.39229912, 0.91312283, 0.39582044, 0.16182233, 0.62411124,
+ 0.062049974, 0.5084992, 0.6835792, 0.98784196, 0.78172857, 0.10788689, 0.1438804, 0.09800406,
+ 0.3960913, 0.13590716, 0.39854, 0.8838793, 0.8747359, 0.40082723, 0.17775355, 0.43851566,
+ 0.99827635, 0.5713145, 0.8552926, 0.94444704, 0.33731982, 0.42541102, 0.74765176, 0.55205274,
+ 0.43713725, 0.28161594, 0.5434486, 0.68305284, 0.80054593, 0.23567316, 0.08136242, 0.7308039,
+ 0.9190936, 0.42697325, 0.12694505, 0.9054515, 0.6885998, 0.32237664, 0.97928506, 0.33159167,
+ 0.43956187, 0.3785934, 0.9559342, 0.7863749, 0.5174173, 0.5265025, 0.05555021, 0.08769297,
+ 0.3469469, 0.77875453, 0.39402276, 0.34180835, 0.5405278, 0.21737531, 0.2867914, 0.636639,
+ 0.76084745, 0.13152646, 0.5507047, 0.50011265, 0.5644382, 0.46082756, 0.29745814, 0.16041815,
+ 0.054544732, 0.6677361, 0.9647857, 0.44776264, 0.27388218, 0.27230206, 0.74991584, 0.67589974,
+ 0.59202945, 0.52370095, 0.50488514, 0.9587264, 0.46947676, 0.9612768, 0.034635436, 0.91063476,
+ 0.22606573, 0.45575568, 0.33610594, 0.02179139, 0.8416504, 0.7395541, 0.19027609, 0.7017183,
+ 0.14018182, 0.49030608, 0.14460404, 0.55707335, 0.7716719, 0.47917238, 0.76715344, 0.9787343,
+ 0.08113525, 0.7955161, 0.7318302, 0.8496812, 0.5617168, 0.60778755, 0.81381077, 0.07464484,
+ 0.028838681, 0.718123, 0.74977887, 0.016826851, 0.71249014, 0.32806498, 0.16716221, 0.7995706,
+ 0.096891016, 0.64007, 0.27404693, 0.10868255, 0.12472161, 0.27566674, 0.31876773, 0.31499064,
+ 0.47746003, 0.2630674, 0.30758083, 0.78357613, 0.12769802, 0.1928425, 0.90422785, 0.112857096,
+ 0.7565475, 0.5261508, 0.8775912, 0.6739607, 0.22944665, 0.18495426, 0.3489179, 0.61827815,
+ 0.6419449, 0.2614611, 0.9929527, 0.12352738, 0.98977524, 0.17344923, 0.9892281, 0.81211686,
+ 0.32314387, 0.34503344, 0.46018234, 0.13160191, 0.20512545, 0.65847087, 0.8540127, 0.8054685,
+ 0.47674835, 0.41683954, 0.37222117, 0.29864943, 0.30020675, 0.03023468, 0.94694686, 0.8359962,
+ 0.8138952, 0.63692176, 0.26027933, 0.18633933, 0.45047382, 0.49320155, 0.570124, 0.91193676,
+ 0.2911521, 0.65576875, 0.46673766, 0.8632605, 0.28271404, 0.19524036, 0.32521543, 0.30401078,
+ 0.27383924, 0.495464, 0.46043226, 0.7826646, 0.7326602, 0.7726259, 0.90773165, 0.09807661,
+ 0.6721381, 0.07212267, 0.1972123, 0.8126071, 0.8127331, 0.05026847, 0.3180714, 0.6117102,
+ 0.31451428, 0.15695652, 0.30963218, 0.35285345, 0.9131699, 0.8028888, 0.36164302, 0.8299423,
+ 0.7749095, 0.54824555, 0.8404498, 0.5493567, 0.19173324, 0.9907522, 0.5227545, 0.281508,
+ 0.091624096, 0.06821037, 0.024810186, 0.80474275, 0.5698024, 0.16428226, 0.10333604, 0.04126928,
+ 0.7291901, 0.16220273, 0.5142012, 0.37835112, 0.29598927, 0.75751686, 0.09920368, 0.24088362,
+ 0.33769736, 0.85502744, 0.5487462, 0.12575752, 0.8856082, 0.972362, 0.3908409, 0.47095042,
+ 0.13382097, 0.63048995, 0.007755094, 0.18441458, 0.9321761, 0.35837498, 0.9063434, 0.6813859,
+ 0.5493682, 0.9157043, 0.720983, 0.7445227, 0.025458287, 0.5133287, 0.041907787, 0.15023202,
+ 0.053620476, 0.2683629, 0.6236633, 0.75096714, 0.28868756, 0.98329186, 0.5339531, 0.017392641,
+ 0.4490419, 0.5995662, 0.21165931, 0.3367058, 0.44200596, 0.39699697, 0.39589983, 0.11926211,
+ 0.6773695, 0.5538598, 0.6709218, 0.93931246, 0.15652716, 0.9189215, 0.10909318, 0.37081516,
+ 0.25585935, 0.83281535, 0.82898295, 0.38028497, 0.03653382, 0.35468096, 0.21542533, 0.8243687,
+ 0.81311965, 0.39851424, 0.07213704, 0.61724526, 0.34869868, 0.63987374, 0.18226288, 0.15052907,
+ 0.096536905, 0.99036247, 0.73537266, 0.3326099, 0.14671567, 0.5696376, 0.2393799, 0.15237123,
+ 0.5198045, 0.6017209, 0.067153245, 0.47159854, 0.84240687, 0.1025953, 0.99370486, 0.134699,
+ 0.15926972, 0.25284818, 0.4951078, 0.45587218, 0.15430894, 0.15366808, 0.9808588, 0.094360925,
+ 0.38414088, 0.3872906, 0.52358615, 0.043491747, 0.32485992, 0.7786546, 0.7705634, 0.037495736,
+ 0.37159687, 0.5203927, 0.8427756, 0.16616471, 0.18354878, 0.7764833, 0.22409947, 0.6862218,
+ 0.59343547, 0.6766117, 0.8604805, 0.4348129, 0.2875277, 0.7438268, 0.9819619, 0.7105244,
+ 0.4048094, 0.937438, 0.45797554, 0.09585048, 0.14476593, 0.7263907, 0.9962201, 0.9428688,
+ 0.009503636, 0.6410118, 0.94846904, 0.7594251, 0.04605143, 0.19588815, 0.8275113, 0.7411499,
+ 0.83115745, 0.02965751, 0.10000168, 0.32201412, 0.25981972, 0.82754016, 0.95115024, 0.38278645,
+ 0.02874871, 0.808886, 0.8624367, 0.47769725, 0.29318756, 0.5460459, 0.8068332, 0.6403141,
+ 0.4053287, 0.8130618, 0.63868237, 0.3874219, 0.320679, 0.67471296, 0.8927298, 0.64520615,
+ 0.5241726, 0.89990675, 0.15666108, 0.54253703, 0.82801425, 0.46467438, 0.64017034, 0.39754733,
+ 0.8491004, 0.11933059, 0.60365546, 0.25787023, 0.6438251, 0.65994775, 0.45070463, 0.57726926,
+ 0.98628783, 0.075189106, 0.06710178, 0.33587992, 0.863954, 0.51852286, 0.64968127, 0.46345773,
+ 0.83417857, 0.30815494, 0.35409638, 0.23298964, 0.5572058, 0.4400894, 0.4204709, 0.1564445,
+ 0.13692771, 0.4547955, 0.7978415, 0.35991296, 0.67087907, 0.4086132, 0.5547722, 0.56407434,
+ 0.16871567, 0.46488938, 0.62859684, 0.17385697, 0.94239044, 0.548963, 0.996489, 0.74538094,
+ 0.36235714, 0.061413143, 0.40113407, 0.24548991, 0.6076112, 0.5568499, 0.78125215, 0.005649717,
+ 0.2502255, 0.69320333, 0.70835847, 0.5198593, 0.110578, 0.4071807, 0.84034157, 0.40901098,
+ 0.6988597, 0.44721094, 0.12094251, 0.1890296, 0.86210626, 0.09079167, 0.90639013, 0.5776746,
+ 0.5204169, 0.50302744, 0.16716424, 0.39906463, 0.8899261, 0.47582427, 0.52106726, 0.2852156,
+ 0.31166598, 0.6087155, 0.87063247, 0.49579263, 0.03895533, 0.174981, 0.5488333, 0.5800778,
+ 0.67354333, 0.7921918, 0.10968746, 0.97767574, 0.70025474, 0.034912895, 0.45349634, 0.761535,
+ 0.6245478, 0.21958585, 0.47499728, 0.4951795, 0.42802048, 0.80745935, 0.8832747, 0.27156547,
+ 0.15502298, 0.8234595, 0.725073, 0.10458374, 0.38968566, 0.38218752, 0.11572367, 0.77440125,
+ 0.17213607, 0.42314288, 0.2081933, 0.5018625, 0.5365482, 0.3445489, 0.37005565, 0.5238787,
+ 0.8983776, 0.5408647, 0.51548624, 0.06991447, 0.9811042, 0.9287144, 0.8774199, 0.48550403,
+ 0.04953112, 0.40562928, 0.7745168, 0.6703402, 0.00082698837, 0.025887761, 0.8571951, 0.5042066,
+ 0.7254408, 0.59906703, 0.34076965, 0.21549584, 0.449908, 0.44424957, 0.19039217, 0.29135585,
+ 0.67646813, 0.33528623, 0.80553967, 0.27711186, 0.8267196, 0.95163375, 0.22498675, 0.2799989,
+ 0.8495302, 0.9511186, 0.5968019, 0.8871558, 0.2919731, 0.8133602, 0.29046127, 0.22630857,
+ 0.9460396, 0.23956898, 0.05505262, 0.98405635, 0.60767066, 0.4453835, 0.77357423, 0.14624831,
+ 0.5659478, 0.7039867, 0.7764218, 0.9374812, 0.0037792725, 0.1545598, 0.073970705, 0.45412806,
+ 0.35047254, 0.2241304, 0.39344636, 0.645818, 0.12317476, 0.600308, 0.65878445, 0.09789734,
+ 0.18064253, 0.49451795, 0.82080996, 0.049708407, 0.42908588, 0.9700393, 0.2122335, 0.9120806,
+ 0.30860576, 0.11446109, 0.26945624, 0.21033902, 0.38919696, 0.20633578, 0.6836851, 0.23108464,
+ 0.56171197, 0.6592914, 0.7111641, 0.122732915, 0.175212, 0.28750554, 0.2762196, 0.69497037,
+ 0.87714785, 0.14267384, 0.53668326, 0.06784272, 0.41991386, 0.6446433, 0.10313381, 0.34573162,
+ 0.58078456, 0.9571553, 0.8034138, 0.11315275, 0.62457347, 0.7238658, 0.71716243, 0.59590846,
+ 0.4917532, 0.8643412, 0.62887543, 0.88931817, 0.8851036, 0.86363167, 0.064931095, 0.14413676,
+ 0.54044527, 0.16236171, 0.084106006, 0.4638834, 0.8891439, 0.5360515, 0.9226853, 0.893137,
+ 0.21829833, 0.12583959, 0.17256053, 0.28641203, 0.4333561, 0.14439079, 0.49216673, 0.6639625,
+ 0.011327274, 0.9237246, 0.62955445, 0.43204167, 0.40292194, 0.5705324, 0.6065112, 0.83784616,
+ 0.94212896, 0.115255654, 0.6309797, 0.3108708, 0.6586301, 0.38690144, 0.8098668, 0.013516203,
+ 0.07774274, 0.39254647, 0.52739745, 0.25755215, 0.5605373, 0.6392504, 0.4565877, 0.044733036,
+ 0.034469932, 0.91027683, 0.8948544, 0.4987339, 0.5513053, 0.4307504, 0.16255233, 0.3473624,
+ 0.3721745, 0.96491295, 0.8779909, 0.961379, 0.2340772, 0.6328894, 0.7412148, 0.9699129,
+ 0.55585057, 0.24625985, 0.52175444, 0.77388823, 0.9050718, 0.61181456, 0.23450689, 0.8313969,
+ 0.31597278, 0.15904433, 0.20866929, 0.04080962, 0.6169933, 0.23461457, 0.1034252, 0.37207687,
+ 0.4671369, 0.58482146, 0.39757174, 0.4926451, 0.67567796, 0.107777245, 0.28654084, 0.5113785,
+ 0.9527033, 0.28361735, 0.9386963, 0.6937171, 0.50891054, 0.84848785, 0.779439, 0.44485334,
+ 0.65133166, 0.55748457, 0.7017016, 0.3142774, 0.11749596, 0.68269944, 0.13966125, 0.42265537,
+ 0.6757699, 0.06345752, 0.18276113, 0.39226097, 0.2220811, 0.12174272, 0.7303691, 0.13755992,
+ 0.8614878, 0.50591403, 0.4942421, 0.64925575, 0.23531766, 0.24856968, 0.29423487, 0.44807333,
+ 0.959719, 0.010375906, 0.82118493, 0.6214544, 0.67311823, 0.5407898, 0.3224864, 0.46748495,
+ 0.37960532, 0.76381594, 0.38947794, 0.05950873, 0.53291297, 0.7891478, 0.2545809, 0.7844374,
+ 0.44516018, 0.97491634, 0.81687516, 0.61222047, 0.9250161, 0.89427984, 0.28929746, 0.83096063,
+ 0.5532483, 0.8011364, 0.8322293, 0.0029964554, 0.35424575, 0.13018323, 0.20953566, 0.402762,
+ 0.2632497, 0.25362825, 0.3545584, 0.10712006, 0.8615145, 0.51820683, 0.7495371, 0.13498017,
+ 0.74097115, 0.7152762, 0.0126556605, 0.45826513, 0.73226476, 0.67086035, 0.6046469, 0.07234,
+ 0.25133318, 0.70980465, 0.20409557, 0.2604013, 0.43169454, 0.6820144, 0.5230572, 0.065439165,
+ 0.72107846, 0.99022436, 0.06820616, 0.87198186, 0.70856047, 0.31948993, 0.11323921, 0.24942209,
+ 0.5542803, 0.9867159, 0.79625905, 0.27928472, 0.4345894, 0.14746083, 0.9229229, 0.9269534,
+ 0.22537923, 0.681895, 0.8712493, 0.20973994, 0.8816242, 0.83103234, 0.098695815, 0.88238794,
+ 0.19648944, 0.75988936, 0.75166327, 0.64444107, 0.9260877, 0.94913435, 0.9710675, 0.5812353,
+ 0.7305711, 0.28911924, 0.3860416, 0.87129015, 0.45000067, 0.87755525, 0.42641973, 0.4214812,
+ 0.60203695, 0.7632336, 0.90398484, 0.74554884, 0.8746013, 0.32536224, 0.6377506, 0.10387234,
+ 0.7868817, 0.2771422, 0.035022065, 0.74979955, 0.8107651, 0.31331727, 0.18381497, 0.8900461,
+ 0.89152855, 0.18581823, 0.6754924, 0.9486711, 0.5678266, 0.4687981, 0.32333443, 0.60514593,
+ 0.015648454, 0.21502374, 0.5487136, 0.14547014, 0.76141924, 0.05163277, 0.4769527, 0.34782398,
+ 0.25547525, 0.44976813, 0.607703, 0.11839061, 0.9270475, 0.35314697, 0.007786621, 0.8711272,
+ 0.12213872, 0.64779097, 0.8575594, 0.64894545, 0.9141123, 0.22126794, 0.77047014, 0.4172538,
+ 0.10530428, 0.4959955, 0.97976166, 0.26418245, 0.20206283, 0.47774863, 0.85365456, 0.13323887,
+ 0.43989918, 0.29883888, 0.7299004, 0.65957755, 0.7766486, 0.49228048, 0.34245312, 0.7352489,
+ 0.8001895, 0.6871981, 0.49432427, 0.360997, 0.70561427, 0.06542435, 0.96299857, 0.5383816,
+ 0.1780316, 0.8043652, 0.82653236, 0.92003566, 0.6112387, 0.67438895, 0.6910336, 0.79438055,
+ 0.44455358, 0.13145985, 0.04016586, 0.26542372, 0.07187113, 0.21277027, 0.14576113, 0.77772665,
+ 0.59611356, 0.47446412, 0.6784915, 0.62820864, 0.62324655, 0.34820905, 0.094478644, 0.62985826,
+ 0.30533785, 0.122310445, 0.84875596, 0.22691421, 0.7269437, 0.40947318, 0.7116395, 0.039879926,
+ 0.5329969, 0.44138008, 0.08615084, 0.39769763, 0.65121627, 0.93361884, 0.52200013, 0.7655102,
+ 0.60780525, 0.9355199, 0.21502401, 0.64518875, 0.45211464, 0.0770294, 0.6633778, 0.5874192,
+ 0.541437, 0.7165977, 0.7648834, 0.2311502, 0.3869329, 0.33478996, 0.915135, 0.82982254,
+ 0.70988655, 0.19667415, 0.6146979, 0.4889283, 0.825633, 0.46411943, 0.067436874, 0.035080392,
+ 0.41982034, 0.0002859342, 0.7324268, 0.630491, 0.12661943, 0.7480635, 0.12651038, 0.6624947,
+ 0.952464, 0.9129812, 0.020403363, 0.6877267, 0.13318504, 0.44928992, 0.1777436, 0.22830844,
+ 0.45893264, 0.2613367, 0.68547726, 0.010346001, 0.6445898, 0.4804893, 0.652947, 0.19820693,
+ 0.52624506, 0.25632828, 0.687811, 0.4545421, 0.31892103, 0.033071853, 0.9398772, 0.14368583,
+ 0.868083, 0.17994362, 0.2253684, 0.4518287, 0.34460258, 0.032886766, 0.4607998, 0.7933734,
+ 0.59008723, 0.10238874, 0.27868623, 0.47395167, 0.3143866, 0.22740832, 0.6966375, 0.26059666,
+ 0.018930554, 0.3863894, 0.029995646, 0.5642963, 0.7786422, 0.05709087, 0.39049065, 0.939331,
+ 0.3473389, 0.53421986, 0.10424597, 0.8702912, 0.060252476, 0.6719683, 0.34357366, 0.9193921,
+ 0.97310406, 0.8767175, 0.8196437, 0.9532414, 0.22392152, 0.7259149, 0.88370585, 0.42604586,
+ 0.80053693, 0.8921038, 0.42025873, 0.54220104, 0.2018031, 0.17899537, 0.8838203, 0.29883677,
+ 0.5596908, 0.42721438, 0.43561155, 0.9325316, 0.0030762074, 0.37558094, 0.36504367, 0.8109921,
+ 0.78945297, 0.2860374, 0.10448979, 0.8103827, 0.9286408, 0.59050864, 0.733121, 0.91811895,
+ 0.75881505, 0.35929412, 0.50084764, 0.4376691, 0.40776464, 0.7433961, 0.036675144, 0.29301566,
+ 0.5026836, 0.6039498, 0.7637594, 0.8865383, 0.6368321, 0.8482896, 0.7375279, 0.16834354,
+ 0.65039957, 0.8054092, 0.31060037, 0.6330381, 0.23635677, 0.41104206, 0.9163159, 0.5975231,
+ 0.51167387, 0.008651535, 0.16378845, 0.93788415, 0.62142515, 0.07332315, 0.49740508, 0.21002825,
+ 0.15898286, 0.5021398, 0.78338593, 0.842509, 0.67814773, 0.44615123, 0.8910721, 0.81629467,
+ 0.39053923, 0.14259589, 0.42984807, 0.39912644, 0.61182153, 0.47850534, 0.17416, 0.94116336,
+ 0.5485095, 0.93614626, 0.15998314, 0.12323159, 0.27990827, 0.10008287, 0.6817622, 0.34777302,
+ 0.4429782, 0.9033245, 0.92599523, 0.39911312, 0.57960767, 0.09879101, 0.6715905, 0.4293604,
+ 0.1065447, 0.55373114, 0.72755545, 0.13469236, 0.06490368, 0.89501894, 0.4901958, 0.20424834,
+ 0.9143371, 0.4943057, 0.24249884, 0.093760885, 0.98119396, 0.5171895, 0.98570156, 0.03316852,
+ 0.83449155, 0.22262509, 0.38937467, 0.6852789, 0.91334003, 0.3741735, 0.93012, 0.05889999,
+ 0.8203776, 0.43561292, 0.3995308, 0.77482325, 0.52015597, 0.491959, 0.23668702, 0.29174823,
+ 0.47100535, 0.0004876647, 0.29258174, 0.058090426, 0.75094986, 0.039467655, 0.8762597, 0.65349054,
+ 0.44595045, 0.9557348, 0.20889449, 0.78560257, 0.857584, 0.5880013, 0.36657903, 0.9257887,
+ 0.917623, 0.89282674, 0.56462157, 0.35698256, 0.70941633, 0.9863116, 0.51602036, 0.7323712,
+ 0.62361115, 0.6686555, 0.31431475, 0.62929076, 0.4954881, 0.71537256, 0.68409234, 0.4223781,
+ 0.2576187, 0.9507506, 0.6227555, 0.98070633, 0.22460775, 0.9276111, 0.28221866, 0.79502386,
+ 0.34636542, 0.73588413, 0.23932843, 0.95760524, 0.165279, 0.1445174, 0.20131597, 0.23237628,
+ 0.069033906, 0.47374207, 0.85720026, 0.62732923, 0.9273374, 0.8797045, 0.5823319, 0.48469374,
+ 0.48446727, 0.5602105, 0.43447927, 0.08229436, 0.7251529, 0.24696892, 0.15800244, 0.7305779,
+ 0.27164242, 0.78651637, 0.52798384, 0.9068334, 0.9652458, 0.3858727, 0.701181, 0.9900118,
+ 0.61060804, 0.7695977, 0.010617126, 0.97353226, 0.74698323, 0.5584152, 0.56709224, 0.47909376,
+ 0.46733952, 0.08193848, 0.56025684, 0.021746036, 0.8581723, 0.056763105, 0.49504068, 0.37791422,
+ 0.36841872, 0.13806179, 0.49623904, 0.66439724, 0.49313185, 0.19992432, 0.06987098, 0.09939649,
+ 0.5778817, 0.50875056, 0.6859628, 0.3787626, 0.6165335, 0.29448256, 0.2671305, 0.6831612,
+ 0.77256113, 0.86718845, 0.016721206, 0.1577397, 0.86908734, 0.60879964, 0.73771054, 0.9260521,
+ 0.9931183, 0.9553855, 0.6149548, 0.6432144, 0.6867121, 0.1362564, 0.8724056, 0.21487932,
+ 0.2914757, 0.15006965, 0.53841466, 0.827184, 0.88963366, 0.03678374, 0.49687997, 0.41068372,
+ 0.69972676, 0.9112206, 0.39565054, 0.23823264, 0.8724524, 0.18832962, 0.8625602, 0.17285694,
+ 0.814808, 0.87709564, 0.24918492, 0.99098384, 0.0400419, 0.337301, 0.50882685, 0.7596191,
+ 0.4003513, 0.5701869, 0.67127895, 0.5377463, 0.58496946, 0.42665657, 0.4126844, 0.4416253,
+ 0.63634497, 0.47108346, 0.08728689, 0.4664639, 0.75606793, 0.4399465, 0.79352754, 0.7357774,
+ 0.3703085, 0.6060375, 0.45801297, 0.9578667, 0.2131491, 0.49947786, 0.05359975, 0.8047887,
+ 0.092825316, 0.4420979, 0.82840645, 0.80961645, 0.8870715, 0.88142174, 0.17483743, 0.95417476,
+ 0.6412428, 0.7787956, 0.4268327, 0.31944674, 0.3655048, 0.9591336, 0.82571423, 0.2730702,
+ 0.49853623, 0.95402527, 0.6018877, 0.4013689, 0.10104273, 0.39609635, 0.41678905, 0.37486148,
+ 0.083568096, 0.5134075, 0.6206753, 0.43400443, 0.879288, 0.5509602, 0.54647, 0.9008734,
+ 0.5165872, 0.86649024, 0.44492102, 0.14287159, 0.59825015, 0.60306793, 0.5545538, 0.7549232,
+ 0.29624605, 0.13311216, 0.8252211, 0.97727233, 0.013113789, 0.4740808, 0.37027258, 0.41117483,
+ 0.7803232, 0.18494278, 0.45933047, 0.25912383, 0.89759016, 0.65223086, 0.70374596, 0.696729,
+ 0.02530885, 0.45354494, 0.72604835, 0.37366393, 0.2607464, 0.740833, 0.07488672, 0.09028263,
+ 0.23232558, 0.5259593, 0.80285954, 0.49901456, 0.5142126, 0.6828427, 0.67482007, 0.8954683,
+ 0.39947143, 0.8469645, 0.10512285, 0.96793056, 0.5708752, 0.43951672, 0.3617477, 0.6094873,
+ 0.14313498, 0.2095005, 0.6536812, 0.69434524, 0.09162968, 0.28734615, 0.0032832306, 0.86435634,
+ 0.1627443, 0.748192, 0.11756273, 0.14470519, 0.8770196, 0.1808899, 0.49417683, 0.55541307,
+ 0.05822544, 0.73493844, 0.7449467, 0.48715448, 0.67122126, 0.871258, 0.8969622, 0.097480536,
+ 0.5101227, 0.5638622, 0.8596524, 0.050625734, 0.547108, 0.7358154, 0.12585375, 0.5857921,
+ 0.09179724, 0.11656108, 0.23052894, 0.051245883, 0.08715177, 0.38054147, 0.99865294, 0.9449794,
+ 0.52267605, 0.93850327, 0.33627024, 0.7660206, 0.56527996, 0.5301148, 0.018448701, 0.21858154,
+ 0.3527876, 0.5497098, 0.90970516, 0.8359368, 0.69457, 0.8745932, 0.93826604, 0.27187696,
+ 0.3125383, 0.5562007, 0.1842225, 0.5277675, 0.42769375, 0.9526575, 0.3172483, 0.42692894,
+ 0.6223383, 0.5317706, 0.05290796, 0.7604585, 0.95036095, 0.44293094, 0.46826127, 0.67768395,
+ 0.7362855, 0.7999673, 0.96447843, 0.732718, 0.53498775, 0.13094164, 0.5322006, 0.9800079,
+ 0.5454135, 0.64107084, 0.6978381, 0.9973982, 0.82611024, 0.28991696, 0.8912221, 0.21720403,
+ 0.17829505, 0.95865196, 0.7387076, 0.5309511, 0.19631897, 0.47088546, 0.5172857, 0.5700186,
+ 0.6212549, 0.90934134, 0.14368229, 0.033509336, 0.4772069, 0.25799018, 0.26822057, 0.9098567,
+ 0.08144851, 0.23202117, 0.09965124, 0.8946027, 0.91011477, 0.20554802, 0.7368892, 0.18159665,
+ 0.024000084, 0.20421462, 0.982354, 0.7866229, 0.2548194, 0.31985012, 0.6008187, 0.33242133,
+ 0.64054847, 0.8357039, 0.58216345, 0.991709, 0.70422333, 0.93731016, 0.481365, 0.26540005,
+ 0.2826816, 0.39445987, 0.1114631, 0.6256465, 0.9872593, 0.49869126, 0.502801, 0.2874233,
+ 0.37285027, 0.78798145, 0.9159497, 0.5940891, 0.19026573, 0.99661946, 0.30708927, 0.972747,
+ 0.22176278, 0.55711097, 0.50695103, 0.99210435, 0.48853147, 0.73066276, 0.31519917, 0.3014048,
+ 0.30852264, 0.81126094, 0.39296088, 0.641503, 0.6758267, 0.27651158, 0.20563333, 0.14413832,
+ 0.7506562, 0.83425117, 0.6119211, 0.5156549, 0.094084926, 0.111242734, 0.1943373, 0.52530885,
+ 0.70141363, 0.6949307, 0.41377264, 0.46683794, 0.4039004, 0.006729609, 0.14215559, 0.643929,
+ 0.52861464, 0.6094164, 0.7699462, 0.1471124, 0.43035918, 0.4892606, 0.7768686, 0.5520188,
+ 0.07926069, 0.8100583, 0.31712383, 0.17599839, 0.105730385, 0.861298, 0.6115966, 0.096338674,
+ 0.5823481, 0.77181137, 0.8434329, 0.35601455, 0.38469836, 0.79143435, 0.8786621, 0.11052005,
+ 0.36277366, 0.9816422, 0.29069075, 0.7936008, 0.31689015, 0.84836125, 0.8975044, 0.30179304,
+ 0.66910535, 0.7490319, 0.1128883, 0.06641029, 0.5065654, 0.058520928, 0.71377915, 0.26139554,
+ 0.057382602, 0.059902266, 0.4363942, 0.28402662, 0.7941189, 0.018338913, 0.41957843, 0.84011555,
+ 0.083334126, 0.31743395, 0.88448983, 0.632089, 0.16329671, 0.78614104, 0.2592306, 0.7371803,
+ 0.7307543, 0.65942615, 0.7843387, 0.448717, 0.19856988, 0.9832678, 0.23512867, 0.23089947,
+ 0.9125539, 0.015330798, 0.50689304, 0.3566985, 0.74840975, 0.5451863, 0.5897733, 0.5238272,
+ 0.05803223, 0.5820373, 0.29863194, 0.3247961, 0.35504016, 0.5946355, 0.31640115, 0.34443474,
+ 0.56206375, 0.45057517, 0.71026665, 0.99945617, 0.9638714, 0.26541534, 0.13849631, 0.8829643,
+ 0.48980126, 0.375708, 0.33565596, 0.84713924, 0.2741822, 0.26506215, 0.06282568, 0.07411481,
+ 0.8247736, 0.20549475, 0.37147272, 0.7787881, 0.5114459, 0.06287994, 0.09170583, 0.53814787,
+ 0.72766066, 0.36066267, 0.5740568, 0.58125937, 0.4875091, 0.93443453, 0.38214013, 0.13611887,
+ 0.343025, 0.439904, 0.88665324, 0.7479947, 0.27300113, 0.23567249, 0.26702806, 0.64713854,
+ 0.8768345, 0.62392867, 0.8668972, 0.37270173, 0.20953032, 0.74263406, 0.249645, 0.79297006,
+ 0.51921165, 0.22451714, 0.50002253, 0.14954542, 0.22316273, 0.53761303, 0.83298886, 0.4991838,
+ 0.35886934, 0.17211881, 0.2717955, 0.6032087, 0.6913585, 0.5572369, 0.3954552, 0.55536675,
+ 0.9935679, 0.19953707, 0.5041142, 0.83427817, 0.3784089, 0.314831, 0.80111367, 0.58910114,
+ 0.93846667, 0.7243342, 0.90195364, 0.8875172, 0.19598271, 0.7190041, 0.3286175, 0.9850266,
+ 0.11101766, 0.78108674, 0.06204771, 0.26299196, 0.434412, 0.23259473, 0.9129562, 0.805412,
+ 0.6069152, 0.38746944, 0.38912535, 0.10088234, 0.96387696, 0.6638193, 0.95578, 0.31959754,
+ 0.22847345, 0.3115305, 0.37913388, 0.009993258, 0.23851983, 0.4153668, 0.41456118, 0.20438069,
+ 0.42340347, 0.9109214, 0.21107873, 0.49882856, 0.6356594, 0.94547164, 0.3032011, 0.6398653,
+ 0.84350127, 0.28676888, 0.49219108, 0.91027176, 0.49518922, 0.13246326, 0.120954745, 0.76097316,
+ 0.28658092, 0.6987022, 0.22736304, 0.99093944, 0.9257056, 0.7002313, 0.6252242, 0.27464733,
+ 0.76855415, 0.5823561, 0.6590438, 0.8844522, 0.3398702, 0.31862426, 0.7465068, 0.6956509,
+ 0.36652556, 0.857667, 0.8395885, 0.5234906, 0.021515984, 0.4141276, 0.16975257, 0.66144353,
+ 0.084268354, 0.74926007, 0.25738105, 0.67710805, 0.17162827, 0.045508236, 0.8244083, 0.0960102,
+ 0.19057575, 0.6181607, 0.72341233, 0.5398176, 0.18800376, 0.4236217, 0.27867505, 0.7231721,
+ 0.28569725, 0.9364314, 0.73027444, 0.05330333, 0.28642786, 0.4187489, 0.29999506, 0.524877,
+ 0.5402621, 0.7965402, 0.54374623, 0.6375222, 0.29287475, 0.59746414, 0.73945713, 0.87245333,
+ 0.5289497, 0.56591946, 0.9066711, 0.17644554, 0.4428503, 0.94811606, 0.10301907, 0.7230459,
+ 0.75794774, 0.5630336, 0.69387645, 0.7217095, 0.5952119, 0.20668921, 0.5076471, 0.9429038,
+ 0.57899195, 0.116416365, 0.23779334, 0.08508458, 0.6838532, 0.11644924, 0.3750157, 0.6655195,
+ 0.44926503, 0.73250407, 0.13684598, 0.37508807, 0.50176203, 0.1868861, 0.80313545, 0.59311163,
+ 0.8787036, 0.850959, 0.0108679095, 0.62208426, 0.5169506, 0.10222952, 0.28032187, 0.3375812,
+ 0.83341235, 0.0072284974, 0.2953556, 0.7233943, 0.7248724, 0.5782856, 0.9296651, 0.3335729,
+ 0.28889313, 0.6008424, 0.05853025, 0.17645839, 0.3596708, 0.6543726, 0.18860014, 0.41250044,
+ 0.19090378, 0.24115163, 0.7271805, 0.7103462, 0.8112701, 0.727931, 0.22128391, 0.5710617,
+ 0.7598981, 0.10076484, 0.8430059, 0.7442529, 0.1958213, 0.8855628, 0.4259532, 0.47676244,
+ 0.8360945, 0.90021217, 0.25167224, 0.67662466, 0.8210937, 0.6516214, 0.940647, 0.8709795,
+ 0.802839, 0.8032731, 0.08619493, 0.9009196, 0.12835586, 0.62667704, 0.2334408, 0.224331,
+ 0.6623589, 0.59836745, 0.4311805, 0.27579898, 0.37504902, 0.5699756, 0.5263111, 0.10548131,
+ 0.7859446, 0.72429395, 0.96349615, 0.6241076, 0.7352797, 0.18541217, 0.13775158, 0.40333033,
+ 0.17488916, 0.5817678, 0.34036386, 0.45945865, 0.40270033, 0.51197547, 0.59140676, 0.5392824,
+ 0.3005046, 0.85620105, 0.9075073, 0.007996995, 0.6417361, 0.3203643, 0.44270578, 0.13322107,
+ 0.86732405, 0.6186749, 0.08189404, 0.59745383, 0.4543823, 0.15015423, 0.10171343, 0.2661189,
+ 0.37390104, 0.14619094, 0.8906801, 0.096799746, 0.68812525, 0.31653944, 0.13569976, 0.6174268,
+ 0.6655215, 0.6828646, 0.72603047, 0.54658806, 0.28631318, 0.77398217, 0.8216307, 0.15038341,
+ 0.0069607063, 0.8918981, 0.97529435, 0.518848, 0.6624684, 0.5183141, 0.46374524, 0.4655803,
+ 0.28158814, 0.83027506, 0.75678355, 0.11660483, 0.10351813, 0.54029775, 0.948948, 0.024734931,
+ 0.48005438, 0.074244976, 0.0855576, 0.2565094, 0.62129533, 0.49460703, 0.85115707, 0.98396516,
+ 0.7205013, 0.2900805, 0.34247547, 0.9588715, 0.5943338, 0.89611775, 0.8469079, 0.09334188,
+ 0.79704416, 0.9315106, 0.59049314, 0.5624842, 0.17485987, 0.5828654, 0.60365057, 0.85558695,
+ 0.6824457, 0.4250998, 0.8152116, 0.8578502, 0.55975586, 0.01909494, 0.5139087, 0.12522376,
+ 0.73391664, 0.7012955, 0.06653367, 0.2120682, 0.6884245, 0.5651213, 0.5290881, 0.51235366,
+ 0.040741026, 0.9913292, 0.7983467, 0.3723879, 0.17583862, 0.50487375, 0.87124646, 0.3854704,
+ 0.9833672, 0.66344166, 0.31956065, 0.1720075, 0.94980466, 0.38646382, 0.8498751, 0.89718896,
+ 0.4705944, 0.22997065, 0.57406366, 0.19619557, 0.67939544, 0.9933069, 0.4242093, 0.70140636,
+ 0.7761718, 0.21725173, 0.22495484, 0.89303833, 0.82958406, 0.6348397, 0.40491733, 0.23192288,
+ 0.40242258, 0.07813944, 0.5217432, 0.18353066, 0.7845187, 0.23126268, 0.6797483, 0.17757194,
+ 0.55385333, 0.42974123, 0.874483, 0.8963142, 0.6995343, 0.34190118, 0.17541912, 0.34745282,
+ 0.85142046, 0.16934472, 0.7414738, 0.4584539, 0.99105763, 0.33289248, 0.8329583, 0.04743413,
+ 0.5671199, 0.09694037, 0.5962161, 0.9585869, 0.2799189, 0.9782081, 0.5558863, 0.3485275,
+ 0.25852436, 0.08763776, 0.76958495, 0.8716652, 0.86472064, 0.6663444, 0.1126702, 0.23933174,
+ 0.55022234, 0.39649174, 0.64234227, 0.24965419, 0.118823886, 0.5278951, 0.0018720366, 0.43427062,
+ 0.04183261, 0.877502, 0.04161787, 0.66023934, 0.8933659, 0.9464634, 0.24086526, 0.069530085,
+ 0.24518117, 0.47430903, 0.61641073, 0.6875784, 0.6350466, 0.7211614, 0.89765304, 0.5756452,
+ 0.87385494, 0.5259555, 0.63778985, 0.6118965, 0.5723162, 0.3037539, 0.48273215, 0.18507604,
+ 0.05667453, 0.5021421, 0.90823156, 0.59456587, 0.69055027, 0.5833041, 0.92861027, 0.039224792,
+ 0.095068336, 0.16194543, 0.9167543, 0.40241688, 0.93659025, 0.895647, 0.4551616, 0.31206095,
+ 0.8467725, 0.7000548, 0.62648404, 0.39041162, 0.049933646, 0.42509183, 0.6042851, 0.8290609,
+ 0.49883872, 0.06669706, 0.37579927, 0.5928684, 0.89010525, 0.3899755, 0.8619544, 0.7380787,
+ 0.39476988, 0.8565418, 0.6035648, 0.39122385, 0.038231853, 0.64629936, 0.37897983, 0.6618771,
+ 0.54569876, 0.577186, 0.59251004, 0.47310117, 0.8044071, 0.49523613, 0.6390549, 0.97820795,
+ 0.07079393, 0.3257289, 0.765124, 0.8722614, 0.6772699, 0.092320524, 0.1351424, 0.6315827,
+ 0.89785695, 0.07917066, 0.09572715, 0.6238532, 0.20750481, 0.33574188, 0.14911953, 0.70509285,
+ 0.29999104, 0.1786756, 0.0076469877, 0.08004845, 0.29208216, 0.063937746, 0.27382907, 0.20047311,
+ 0.32107502, 0.96460694, 0.84471285, 0.47274768, 0.8325818, 0.13118395, 0.024653764, 0.0036025788,
+ 0.42764217, 0.39759132, 0.52207446, 0.56437635, 0.62485147, 0.989693, 0.060808785, 0.30244938,
+ 0.7213994, 0.9719821, 0.49336693, 0.9590612, 0.5505722, 0.75512666, 0.4543723, 0.2099569,
+ 0.42806646, 0.8874172, 0.17311013, 0.6257315, 0.48758915, 0.55900645, 0.68612576, 0.0068561803,
+ 0.051899806, 0.56465095, 0.5511864, 0.71266294, 0.2476077, 0.6623947, 0.7990009, 0.76667297,
+ 0.054516893, 0.092124574, 0.19621104, 0.80991346, 0.8136675, 0.58474314, 0.08024137, 0.31029803,
+ 0.117866814, 0.70519763, 0.35864902, 0.32010004, 0.5705708, 0.3147679, 0.64990085, 0.56594837,
+ 0.51023465, 0.6347559, 0.044681232, 0.94516456, 0.9580738, 0.39892223, 0.51601344, 0.8686357,
+ 0.71146554, 0.51521826, 0.51247656, 0.06020054, 0.43850663, 0.3481458, 0.054841675, 0.059004717,
+ 0.1729812, 0.7266939, 0.9045443, 0.45844766, 0.5589156, 0.6444588, 0.39628944, 0.8433233,
+ 0.8071758, 0.8628121, 0.5078647, 0.78239155, 0.20035744, 0.36602575, 0.43628535, 0.7371319,
+ 0.91475004, 0.985238, 0.20242831, 0.61285174, 0.6177135, 0.8538363, 0.8085992, 0.65559465,
+ 0.57611114, 0.32757533, 0.09844793, 0.2984492, 0.07226656, 0.020040827, 0.87179136, 0.769721,
+ 0.65035594, 0.2996443, 0.14711884, 0.8438769, 0.4102236, 0.1914532, 0.007032739, 0.8657759,
+ 0.23846649, 0.20135792, 0.13798875, 0.09526171, 0.8910575, 0.7336219, 0.6682783, 0.34543982,
+ 0.078932896, 0.77534467, 0.14545049, 0.45326862, 0.14571752, 0.44198993, 0.44129124, 0.31914487,
+ 0.9180948, 0.24894963, 0.8823365, 0.23134027, 0.54601085, 0.09784024, 0.7710568, 0.787135,
+ 0.99102074, 0.73814374, 0.13203558, 0.90071315, 0.2189069, 0.5924085, 0.32690832, 0.7232968,
+ 0.97820526, 0.33665246, 0.37438527, 0.41635555, 0.71584755, 0.7133375, 0.76453716, 0.84248924,
+ 0.6592971, 0.7530081, 0.2195163, 0.29692188, 0.87459034, 0.41852275, 0.62400347, 0.20836602,
+ 0.8583531, 0.82797396, 0.9257821, 0.16127396, 0.3091167, 0.77569246, 0.31976497, 0.14062625,
+ 0.43030116, 0.35085374, 0.104240976, 0.15291376, 0.6015863, 0.76756513, 0.12653293, 0.48652443,
+ 0.44843635, 0.42215365, 0.47506335, 0.80906504, 0.06760467, 0.02493567, 0.6032973, 0.20475733,
+ 0.48441246, 0.039847255, 0.5720432, 0.7930028, 0.8783239, 0.47413486, 0.91254467, 0.57249796,
+ 0.11414025, 0.9236696, 0.042360075, 0.39093295, 0.6666264, 0.16563436, 0.41418016, 0.20251282,
+ 0.016887465, 0.23375902, 0.9860544, 0.36499384, 0.60909647, 0.6116234, 0.24090295, 0.891732,
+ 0.6264752, 0.7329919, 0.8484855, 0.45243672, 0.9434594, 0.8149384, 0.14076136, 0.8334174,
+ 0.22467664, 0.72102475, 0.6768615, 0.26926944, 0.20364925, 0.52676225, 0.2623023, 0.95616627,
+ 0.43830907, 0.531743, 0.03877351, 0.67791677, 0.72520506, 0.7356, 0.81989807, 0.282802,
+ 0.007973485, 0.27255052, 0.7921776, 0.8338457, 0.038881265, 0.23830348, 0.59566087, 0.872789,
+ 0.7989443, 0.68031126, 0.16652757, 0.14533207, 0.62564933, 0.46010798, 0.6290386, 0.29920182,
+ 0.7829082, 0.20894268, 0.16625631, 0.94560164, 0.48877287, 0.14491072, 0.9988636, 0.49012524,
+ 0.9714567, 0.029888112, 0.92668474, 0.07735347, 0.5728499, 0.5629862, 0.16652691, 0.8908752,
+ 0.91309386, 0.56568354, 0.44446322, 0.67090887, 0.022760825, 0.3069157, 0.7945361, 0.9863731,
+ 0.12536389, 0.80407244, 0.47032514, 0.523338, 0.36023465, 0.11697024, 0.33051696, 0.9782011,
+ 0.9027044, 0.7395717, 0.89500856, 0.51626235, 0.5693437, 0.8742964, 0.7940291, 0.86306274,
+ 0.27368698, 0.30205235, 0.86238897, 0.008993154, 0.31161872, 0.5183074, 0.29993913, 0.2359581,
+ 0.51378435, 0.27565238, 0.23223823, 0.059965752, 0.01564475, 0.9581297, 0.276441, 0.4759925,
+ 0.41440654, 0.17988315, 0.82023776, 0.68470037, 0.6745856, 0.47552556, 0.12989059, 0.85448647,
+ 0.69937116, 0.94848365, 0.17464903, 0.83327824, 0.6679777, 0.65026456, 0.32153153, 0.038797423,
+ 0.7716544, 0.58140045, 0.3972219, 0.7207085, 0.44452676, 0.78554296, 0.67475444, 0.6070565,
+ 0.50413334, 0.23436703, 0.009553685, 0.08458229, 0.884732, 0.27055123, 0.96255636, 0.9445748,
+ 0.46313068, 0.41901603, 0.10185582, 0.38946053, 0.05405868, 0.10932874, 0.18847717, 0.79816145,
+ 0.17216177, 0.007902476, 0.30962202, 0.36313507, 0.34365836, 0.46666092, 0.5679804, 0.8635198,
+ 0.9541208, 0.19344081, 0.2883113, 0.4342443, 0.5609078, 0.55573255, 0.03146575, 0.6288636,
+ 0.50512874, 0.21318124, 0.18056706, 0.44021857, 0.46597186, 0.045308296, 0.96975446, 0.42881992,
+ 0.9859273, 0.23007429, 0.37014756, 0.24896163, 0.54840875, 0.932071, 0.98473877, 0.6623257,
+ 0.39292327, 0.5990605, 0.5485467, 0.4366243, 0.47592095, 0.31161934, 0.26339814, 0.037472416,
+ 0.6663866, 0.1460339, 0.13046144, 0.6912912, 0.9822399, 0.528312, 0.38366696, 0.90739816,
+ 0.3875503, 0.47299224, 0.88433176, 0.8408774, 0.92876166, 0.7482586, 0.33218956, 0.12685347,
+ 0.038148023, 0.8808021, 0.37720776, 0.11358407, 0.09651337, 0.3190188, 0.31511107, 0.022049852,
+ 0.20870206, 0.6259856, 0.041321024, 0.9618473, 0.007185834, 0.5948415, 0.15294261, 0.19350938,
+ 0.9497831, 0.14309464, 0.77383196, 0.31993797, 0.91484684, 0.27846324, 0.44658, 0.45761526,
+ 0.8464073, 0.46274942, 0.86141133, 0.075416476, 0.0477392, 0.14386131, 0.733564, 0.64466465,
+ 0.26687092, 0.42169324, 0.39847627, 0.5951189, 0.9344116, 0.14981407, 0.94095904, 0.3473678,
+ 0.83092284, 0.108411595, 0.48258916, 0.3562543, 0.48699102, 0.42181966, 0.9002123, 0.7927088,
+ 0.32004964, 0.6908224, 0.8910943, 0.78566706, 0.9744266, 0.012251603, 0.21200661, 0.7596848,
+ 0.4342221, 0.9195925, 0.26717675, 0.63376397, 0.45760745, 0.2396946, 0.97431064, 0.06484076,
+ 0.8924216, 0.39665636, 0.6949764, 0.5854926, 0.1963652, 0.5578238, 0.2590978, 0.799969,
+ 0.2021356, 0.42646417, 0.48901513, 0.8064353, 0.7958741, 0.0903257, 0.9706242, 0.42458767,
+ 0.56253713, 0.068702534, 0.75536686, 0.3569168, 0.25276697, 0.94789696, 0.670238, 0.2546193,
+ 0.2096866, 0.6387915, 0.16089676, 0.01481907, 0.8826373, 0.3071951, 0.8897603, 0.59122825,
+ 0.13410094, 0.4177484, 0.4638327, 0.09033466, 0.72684324, 0.3147197, 0.5963436, 0.76222587,
+ 0.43172458, 0.091125324, 0.58353144, 0.5479625, 0.52323645, 0.40557137, 0.9638107, 0.3438964,
+ 0.9489683, 0.8425891, 0.07122685, 0.38890493, 0.48432773, 0.61739385, 0.8120738, 0.9445246,
+ 0.7264184, 0.4403571, 0.375806, 0.55757374, 0.396927, 0.24427874, 0.9173317, 0.8949405,
+ 0.5367038, 0.8977869, 0.6723343, 0.3781257, 0.626493, 0.88028955, 0.6977444, 0.24781741,
+ 0.4723589, 0.993141, 0.9251922, 0.16164163, 0.36436552, 0.12227554, 0.73138285, 0.80411524,
+ 0.6749808, 0.8170004, 0.06585078, 0.040048227, 0.23596825, 0.5008554, 0.10690048, 0.51670706,
+ 0.6056746, 0.5193081, 0.3639163, 0.28648618, 0.9389137, 0.03876988, 0.36529887, 0.18744585,
+ 0.17379361, 0.68859094, 0.011258623, 0.62544954, 0.733237, 0.585685, 0.7174034, 0.06867873,
+ 0.14484468, 0.82340944, 0.916546, 0.49118677, 0.6922017, 0.65043217, 0.58015907, 0.60414284,
+ 0.70897424, 0.57169074, 0.8825929, 0.5799266, 0.17842796, 0.8772835, 0.65897226, 0.03584844,
+ 0.7908864, 0.15562724, 0.7724511, 0.10718488, 0.5163733, 0.41125825, 0.3089037, 0.43358904,
+ 0.62784207, 0.73774636, 0.98784804, 0.6757746, 0.111016914, 0.10593328, 0.07087821, 0.08929581,
+ 0.09959695, 0.99717206, 0.89520353, 0.4125588, 0.5843094, 0.6157137, 0.82450545, 0.95524246,
+ 0.939149, 0.7597735, 0.5775119, 0.36722296, 0.15617695, 0.78537226, 0.009017896, 0.29651013,
+ 0.029618707, 0.97541016, 0.83456314, 0.5776098, 0.8132339, 0.6102185, 0.55230546, 0.73358643,
+ 0.51450574, 0.48295695, 0.86334467, 0.9544553, 0.6625841, 0.90438455, 0.49312592, 0.603041,
+ 0.50081253, 0.7932971, 0.4803297, 0.1812559, 0.9820799, 0.24641345, 0.45153904, 0.1751727,
+ 0.3311218, 0.81720865, 0.16803588, 0.7565998, 0.8337463, 0.9416807, 0.2774121, 0.8424698,
+ 0.7287285, 0.6913379, 0.64615583, 0.13560674, 0.27137014, 0.4932684, 0.27606192, 0.48937842,
+ 0.4448666, 0.16161712, 0.89805305, 0.10135246, 0.75236905, 0.87005013, 0.29265827, 0.034764472,
+ 0.26664755, 0.9744709, 0.86641043, 0.3628798, 0.30504256, 0.827762, 0.31443018, 0.7832053,
+ 0.5238711, 0.65939045, 0.246488, 0.9960252, 0.44218266, 0.7957057, 0.8998401, 0.572825,
+ 0.20554484, 0.020874852, 0.22572684, 0.97124624, 0.2582287, 0.35751918, 0.33167085, 0.007544129,
+ 0.5172352, 0.99095124, 0.73638934, 0.8204628, 0.34836042, 0.3501866, 0.4228037, 0.46107167,
+ 0.5245504, 0.1332714, 0.48995224, 0.8592754, 0.07527029, 0.91453224, 0.53742725, 0.90096647,
+ 0.3769077, 0.8629506, 0.6117356, 0.61197966, 0.2467804, 0.2800367, 0.047195755, 0.6491609,
+ 0.261777, 0.32522804, 0.8958076, 0.7314942, 0.6443233, 0.32141203, 0.7765358, 0.90912837,
+ 0.6428001, 0.85886633, 0.8456446, 0.31409132, 0.09137268, 0.49396735, 0.43484485, 0.17368458,
+ 0.23658675, 0.78541636, 0.47147486, 0.30891126, 0.30575344, 0.040564716, 0.49755472, 0.2910126,
+ 0.48344758, 0.32476038, 0.59433854, 0.39527807, 0.7457836, 0.71969116, 0.76076376, 0.23719852,
+ 0.9437555, 0.087228395, 0.55868584, 0.023132376, 0.45437896, 0.6913095, 0.8167484, 0.20313835,
+ 0.35673562, 0.58082384, 0.2164753, 0.21640398, 0.06888765, 0.22333595, 0.8095938, 0.88294035,
+ 0.42810574, 0.43805102, 0.37539294, 0.46136406, 0.80856186, 0.7382845, 0.34340748, 0.2212123,
+ 0.8276733, 0.60479504, 0.24804658, 0.3195629, 0.7270735, 0.3812577, 0.16334477, 0.92310894,
+ 0.09810257, 0.6084461, 0.37033582, 0.004144284, 0.9352815, 0.41171247, 0.71930563, 0.54527724,
+ 0.968668, 0.2683365, 0.9521756, 0.7249296, 0.8240894, 0.28115076, 0.22212493, 0.26011166,
+ 0.5151666, 0.71139824, 0.9671723, 0.3077326, 0.3442982, 0.29939967, 0.42863667, 0.20547101,
+ 0.7438209, 0.33747354, 0.19545908, 0.8495839, 0.44326293, 0.49718547, 0.4760649, 0.97547793,
+ 0.4174791, 0.29336637, 0.11830141, 0.46044156, 0.85300016, 0.8054495, 0.9476588, 0.016393282,
+ 0.7187454, 0.8301157, 0.49269608, 0.5402253, 0.78610885, 0.6184779, 0.39712286, 0.54652256,
+ 0.3826701, 0.98793495, 0.80439633, 0.015675247, 0.4140854, 0.85561216, 0.5788107, 0.7987029,
+ 0.17980942, 0.16486481, 0.26032335, 0.597808, 0.2162534, 0.86972165, 0.102014296, 0.47148252,
+ 0.7922716, 0.97669774, 0.3074505, 0.53072304, 0.16284934, 0.7616834, 0.40711153, 0.7097171,
+ 0.7637394, 0.950779, 0.58898723, 0.5141825, 0.8067036, 0.88841134, 0.41936216, 0.12534304,
+ 0.94035065, 0.6489365, 0.46691382, 0.45532802, 0.69278914, 0.46038964, 0.56139255, 0.56186694,
+ 0.7145557, 0.31959853, 0.28063214, 0.6881353, 0.54512614, 0.3498508, 0.8001399, 0.8490237,
+ 0.7281014, 0.021213572, 0.7479538, 0.8094111, 0.31102738, 0.8663998, 0.38367322, 0.6209867,
+ 0.5808234, 0.09467922, 0.25193584, 0.46330634, 0.26662496, 0.06462818, 0.99199927, 0.29139808,
+ 0.74550265, 0.13498032, 0.65745735, 0.5673169, 0.40280786, 0.64668626, 0.7786934, 0.33188194,
+ 0.4153052, 0.7455836, 0.8161674, 0.8432508, 0.48105124, 0.7189762, 0.16459095, 0.41388863,
+ 0.15063916, 0.73996353, 0.78608114, 0.78549004, 0.14045759, 0.609951, 0.8143157, 0.07395084,
+ 0.26526332, 0.8459271, 0.8745046, 0.5981099, 0.20845382, 0.098086186, 0.29524195, 0.6499275,
+ 0.32759923, 0.98923403, 0.9426327, 0.41014582, 0.6923934, 0.23282301, 0.44621587, 0.08141512,
+ 0.24252021, 0.4160718, 0.3941059, 0.5654438, 0.050232418, 0.5404224, 0.13993548, 0.8618472,
+ 0.9300883, 0.8380472, 0.31266716, 0.52666146, 0.27854705, 0.20650926, 0.1509405, 0.13555165,
+ 0.32066464, 0.5835065, 0.30205357, 0.5568808, 0.7721817, 0.18058343, 0.123428136, 0.31721902,
+ 0.45034164, 0.16623993, 0.5156516, 0.4918172, 0.7763435, 0.75444514, 0.7214952, 0.91781616,
+ 0.29374766, 0.704666, 0.5429698, 0.7243858, 0.21584511, 0.24887188, 0.02371842, 0.7248409,
+ 0.7059916, 0.012657363, 0.6680217, 0.37040663, 0.785419, 0.7685805, 0.37138042, 0.12108998,
+ 0.83829355, 0.80708104, 0.08948117, 0.108886935, 0.93076944, 0.8893351, 0.30923343, 0.061936773,
+ 0.29264367, 0.07688689, 0.11510216, 0.8839925, 0.02477082, 0.64811826, 0.08550372, 0.17564313,
+ 0.11655201, 0.39485103, 0.23291379, 0.57388103, 0.6635394, 0.42655468, 0.9197065, 0.071792774,
+ 0.5597881, 0.57721263, 0.8508891, 0.75952435, 0.5125618, 0.75302154, 0.53180003, 0.6817611,
+ 0.79485947, 0.3945616, 0.6535236, 0.9692625, 0.66496396, 0.61260825, 0.98704666, 0.40441254,
+ 0.3954326, 0.48103306, 0.43174213, 0.13895822, 0.13376972, 0.13972592, 0.7000701, 0.05787335,
+ 0.92715365, 0.49237853, 0.2538546, 0.390568, 0.5356667, 0.7974994, 0.45755056, 0.41173887,
+ 0.8873745, 0.017688395, 0.54909885, 0.3535568, 0.038445998, 0.54970914, 0.549375, 0.5396221,
+ 0.54508686, 0.43334106, 0.089132994, 0.6302092, 0.99459463, 0.11624123, 0.5106792, 0.50394374,
+ 0.40780434, 0.8285013, 0.17844845, 0.18250638, 0.99481255, 0.7807483, 0.93802303, 0.42006215,
+ 0.87714255, 0.7930158, 0.8323707, 0.020183232, 0.4991669, 0.14123203, 0.1460944, 0.9973601,
+ 0.93701106, 0.24178477, 0.081888, 0.64727557, 0.06350941, 0.6334899, 0.36596653, 0.84572345,
+ 0.931658, 0.89212, 0.59387136, 0.70042866, 0.050592937, 0.06986087, 0.063278705, 0.81091243,
+ 0.98169935, 0.74991083, 0.98276365, 0.7071655, 0.6190509, 0.27504414, 0.41692632, 0.106626175,
+ 0.07966534, 0.12903668, 0.47641423, 0.24543023, 0.71733844, 0.5291918, 0.040455237, 0.40385485,
+ 0.28724664, 0.091772884, 0.69319814, 0.7528099, 0.034353238, 0.8634036, 0.44043434, 0.77431446,
+ 0.46253473, 0.332725, 0.25084835, 0.10269255, 0.18687698, 0.23759438, 0.36946923, 0.8072817,
+ 0.72973704, 0.021458272, 0.038483858, 0.7492561, 0.1584684, 0.43892893, 0.37830916, 0.6619669,
+ 0.8248584, 0.9752618, 0.5676102, 0.93447274, 0.15707563, 0.120536305, 0.12838502, 0.40246627,
+ 0.8516648, 0.19001648, 0.41318202, 0.95882004, 0.3766627, 0.31046882, 0.7765592, 0.11829578,
+ 0.3094765, 0.20844917, 0.24463072, 0.28632593, 0.024195805, 0.31423378, 0.9197492, 0.84207094,
+ 0.75956744, 0.66913253, 0.5156932, 0.6958802, 0.4907079, 0.29119918, 0.24538647, 0.8483177,
+ 0.7134637, 0.031231258, 0.92795146, 0.059091415, 0.29579335, 0.5059616, 0.6172388, 0.34199843,
+ 0.20433997, 0.84838206, 0.2510278, 0.9968605, 0.82441235, 0.41064918, 0.43061897, 0.41926822,
+ 0.2448991, 0.92018807, 0.43977955, 0.95001924, 0.19429821, 0.09198324, 0.63777107, 0.51062465,
+ 0.055512622, 0.72553927, 0.17490527, 0.48794308, 0.60484314, 0.43250486, 0.91175836, 0.5604656,
+ 0.94463, 0.56486434, 0.24535634, 0.34543145, 0.38251737, 0.7174677, 0.82250243, 0.8035149,
+ 0.59121037, 0.9026323, 0.081985965, 0.17581372, 0.06320599, 0.9228887, 0.017658591, 0.3489183,
+ 0.23851357, 0.096424945, 0.45098105, 0.57051986, 0.8514196, 0.29536724, 0.6540195, 0.62148046,
+ 0.39346015, 0.41732678, 0.0035787956, 0.5702541, 0.33105636, 0.12929575, 0.7371553, 0.7718351,
+ 0.93662375, 0.6905622, 0.052230474, 0.25954804, 0.16529284, 0.08518753, 0.03675085, 0.52743137,
+ 0.097685665, 0.6362647, 0.35880888, 0.2916659, 0.009997273, 0.46195737, 0.4474187, 0.13262391,
+ 0.7078807, 0.825987, 0.24942951, 0.5084182, 0.9815238, 0.3412385, 0.70904595, 0.6492628,
+ 0.9108448, 0.62387586, 0.9519713, 0.9651906, 0.71388894, 0.25224832, 0.4724585, 0.4619146,
+ 0.16547702, 0.31015086, 0.23919, 0.37264377, 0.8706582, 0.7581105, 0.18362544, 0.15332605,
+ 0.05967409, 0.9235497, 0.47283417, 0.21515496, 0.93655837, 0.3623536, 0.6114832, 0.93150276,
+ 0.9699081, 0.8709549, 0.8623734, 0.5050694, 0.87986624, 0.2287371, 0.7903113, 0.5953852,
+ 0.98151624, 0.40296772, 0.34870324, 0.541417, 0.13321623, 0.07156025, 0.81354237, 0.84543735,
+ 0.16380614, 0.8968943, 0.12618889, 0.6998464, 0.22276738, 0.07477489, 0.2619657, 0.94977015,
+ 0.6423615, 0.09610346, 0.4487441, 0.05797409, 0.8684043, 0.49389097, 0.7127044, 0.54849124,
+ 0.012392659, 0.020468513, 0.99528253, 0.8429341, 0.3898749, 0.96738917, 0.58204836, 0.9367399,
+ 0.5198395, 0.6438048, 0.39112753, 0.46769053, 0.40940732, 0.64220846, 0.02010981, 0.9881138,
+ 0.11000732, 0.6273968, 0.051348828, 0.039664086, 0.2361647, 0.91163677, 0.7087354, 0.8951332,
+ 0.6089892, 0.91260326, 0.86270785, 0.7837628, 0.779993, 0.73233724, 0.72698087, 0.48762527,
+ 0.69026333, 0.800212, 0.5290243, 0.11274772, 0.07627774, 0.9706083, 0.45556244, 0.19641699,
+ 0.31484595, 0.18944897, 0.18000686, 0.5789626, 0.6836474, 0.79427516, 0.54036283, 0.00015307916,
+ 0.07599365, 0.46063024, 0.94796675, 0.24100749, 0.44254217, 0.67304033, 0.31232652, 0.10075587,
+ 0.31173313, 0.100149296, 0.23394488, 0.47727165, 0.10468131, 0.79828554, 0.1567469, 0.78750235,
+ 0.9168239, 0.9035022, 0.7774272, 0.6091953, 0.11318414, 0.9073621, 0.9118361, 0.139399,
+ 0.17183441, 0.85493183, 0.7248181, 0.04671574, 0.7316299, 0.1297728, 0.21148583, 0.814714,
+ 0.37224042, 0.8625547, 0.70776916, 0.31936276, 0.7843705, 0.4859734, 0.04508312, 0.017223012,
+ 0.4878855, 0.42826846, 0.8010146, 0.97612846, 0.73666346, 0.9782908, 0.09173568, 0.51656044,
+ 0.032702066, 0.3925045, 0.6621387, 0.7801451, 0.01684795, 0.93116754, 0.886969, 0.16863157,
+ 0.54879415, 0.80856776, 0.06917309, 0.5876103, 0.94822216, 0.26561078, 0.36912593, 0.18196031,
+ 0.8886635, 0.41923082, 0.1050312, 0.24212655, 0.09051639, 0.8373841, 0.0031318855, 0.4308505,
+ 0.8584191, 0.7602042, 0.121309794, 0.68491566, 0.10634747, 0.9357077, 0.4027356, 0.19354361,
+ 0.7631962, 0.2082577, 0.014013676, 0.3391254, 0.46763408, 0.43134072, 0.7978661, 0.44107288,
+ 0.9755858, 0.5391376, 0.7705686, 0.9758027, 0.4168003, 0.4574728, 0.06900084, 0.22227472,
+ 0.059142508, 0.6190543, 0.08746498, 0.3174326, 0.8732596, 0.84960914, 0.42604402, 0.19531794,
+ 0.38937265, 0.2312882, 0.921726, 0.25664374, 0.8098577, 0.20205325, 0.06228409, 0.61308646,
+ 0.40583217, 0.8756295, 0.8244142, 0.7399645, 0.2515971, 0.030000538, 0.7143262, 0.45732272,
+ 0.6213647, 0.6639583, 0.26654074, 0.5513788, 0.0668155, 0.02732918, 0.014050223, 0.40094635,
+ 0.69120336, 0.8990351, 0.6257732, 0.48729318, 0.8482427, 0.08530297, 0.320284, 0.91358703,
+ 0.7822137, 0.8186957, 0.94975275, 0.2363459, 0.50961477, 0.54122233, 0.63121516, 0.77353257,
+ 0.4768535, 0.15748215, 0.56997055, 0.54117084, 0.6330586, 0.32903638, 0.9706776, 0.02914197,
+ 0.90472806, 0.6301423, 0.69606787, 0.20930128, 0.5830684, 0.8746652, 0.12850243, 0.36204344,
+ 0.21723796, 0.5207796, 0.5654404, 0.9108227, 0.57628006, 0.5749909, 0.7648438, 0.3205292,
+ 0.5553455, 0.91082716, 0.9577508, 0.43290135, 0.08024777, 0.47798032, 0.94770795, 0.0801424,
+ 0.03274318, 0.49300817, 0.07452531, 0.90933335, 0.45735866, 0.4728794, 0.7678877, 0.362167,
+ 0.9283575, 0.5966312, 0.5825651, 0.21810043, 0.3892351, 0.11098274, 0.33051863, 0.9075484,
+ 0.6901933, 0.5877093, 0.019107932, 0.9888351, 0.9757819, 0.72039247, 0.19725248, 0.90186256,
+ 0.39263836, 0.24944134, 0.98582536, 0.72223145, 0.3712856, 0.5377763, 0.9488942, 0.42674774,
+ 0.68243426, 0.6159255, 0.1765581, 0.09006023, 0.8001399, 0.21916907, 0.9046848, 0.74435854,
+ 0.7528919, 0.20327342, 0.9824652, 0.9796489, 0.9924258, 0.5467434, 0.9312941, 0.44436273,
+ 0.58030856, 0.05020233, 0.742708, 0.49253845, 0.4588724, 0.95887285, 0.10436046, 0.31235072,
+ 0.29575568, 0.17266272, 0.516695, 0.20791732, 0.48705408, 0.045656245, 0.9908814, 0.3905812,
+ 0.647737, 0.15581739, 0.5356661, 0.77330965, 0.93442464, 0.2404584, 0.10740854, 0.47102425,
+ 0.6830245, 0.27474937, 0.2359432, 0.7725085, 0.73792726, 0.21760361, 0.9094368, 0.845895,
+ 0.31814724, 0.5414626, 0.14192294, 0.32108325, 0.7950682, 0.45635575, 0.96787536, 0.72356147,
+ 0.511565, 0.8642074, 0.79430455, 0.62747717, 0.70247406, 0.6967675, 0.2573045, 0.7072357,
+ 0.212392, 0.591884, 0.33191186, 0.8366084, 0.01107724, 0.15798447, 0.5099381, 0.33985013,
+ 0.9427938, 0.27168378, 0.8095139, 0.18412302, 0.72292966, 0.33185193, 0.5744235, 0.078152075,
+ 0.2632259, 0.67080003, 0.8897701, 0.94559145, 0.9037333, 0.66979814, 0.595513, 0.19138126,
+ 0.18794204, 0.8121047, 0.26174462, 0.07021725, 0.44615385, 0.47993135, 0.76855016, 0.986257,
+ 0.017444894, 0.5287075, 0.5601165, 0.1460432, 0.88569176, 0.07282839, 0.8348177, 0.16016278,
+ 0.031524524, 0.80207276, 0.37828946, 0.52338445, 0.6468418, 0.7837523, 0.00063179433, 0.17971309,
+ 0.2897839, 0.7161524, 0.3642513, 0.031674027, 0.8069974, 0.31171304, 0.8035024, 0.54259384,
+ 0.9963711, 0.14053062, 0.6486664, 0.19897254, 0.8962398, 0.43972084, 0.8936963, 0.46286246,
+ 0.5031336, 0.8232569, 0.16667813, 0.19422211, 0.7717354, 0.42838028, 0.19246033, 0.19039753,
+ 0.8359823, 0.7296073, 0.9140669, 0.10166052, 0.29150867, 0.07212853, 0.54453945, 0.40418974,
+ 0.8114729, 0.08203155, 0.78043336, 0.7300014, 0.11568007, 0.73687613, 0.1792596, 0.70573187,
+ 0.7252052, 0.017522655, 0.14967212, 0.7451611, 0.42416203, 0.6358452, 0.26392296, 0.59180367,
+ 0.9083765, 0.915427, 0.020250821, 0.8235849, 0.6170742, 0.80640966, 0.40797767, 0.86140364,
+ 0.52369213, 0.17385374, 0.19569172, 0.07739012, 0.3976461, 0.70184183, 0.2510852, 0.92424256,
+ 0.59599113, 0.24447663, 0.38749963, 0.81420827, 0.6592875, 0.16369487, 0.34718236, 0.76625746,
+ 0.6439973, 0.46094626, 0.46901694, 0.75421274, 0.27870816, 0.44729918, 0.76623553, 0.20013711,
+ 0.46568435, 0.32226324, 0.193284, 0.37608168, 0.051877704, 0.72095454, 0.7871155, 0.0050632227,
+ 0.6740539, 0.9190297, 0.20630927, 0.94182634, 0.5411844, 0.10186948, 0.30808574, 0.023363324,
+ 0.7664375, 0.22542956, 0.14916998, 0.17968538, 0.24834555, 0.44971466, 0.93251616, 0.74468166,
+ 0.56824464, 0.25399336, 0.17958756, 0.15612793, 0.33739275, 0.6537649, 0.5826955, 0.07639295,
+ 0.40761822, 0.9955546, 0.6117058, 0.07538286, 0.50855786, 0.8750035, 0.8723649, 0.8750366,
+ 0.4573611, 0.38243642, 0.1401544, 0.7402578, 0.9573856, 0.40535605, 0.22507304, 0.54212785,
+ 0.1528605, 0.44565362, 0.98777527, 0.05327858, 0.2981292, 0.5865501, 0.9517916, 0.015969688,
+ 0.38974705, 0.44860238, 0.807837, 0.79788435, 0.541367, 0.6309876, 0.6676705, 0.02028897,
+ 0.33633423, 0.12991633, 0.5342081, 0.5456298, 0.4901637, 0.2327029, 0.5148055, 0.89143395,
+ 0.35306472, 0.27413338, 0.7223243, 0.86590916, 0.30956024, 0.1922584, 0.787296, 0.1628886,
+ 0.02892033, 0.6374597, 0.0032674163, 0.89173913, 0.66598964, 0.5294169, 0.77826375, 0.8210681,
+ 0.043763056, 0.5957361, 0.6856358, 0.05995547, 0.06716649, 0.07448051, 0.3336696, 0.8263735,
+ 0.7147659, 0.11986544, 0.40392354, 0.8274693, 0.87114793, 0.67944324, 0.051964145, 0.9201576,
+ 0.9308481, 0.096341334, 0.70021385, 0.02399584, 0.8642258, 0.08588241, 0.70640945, 0.19748867,
+ 0.6613063, 0.6449484, 0.768964, 0.9039073, 0.6277202, 0.77593136, 0.35429934, 0.8069173,
+ 0.3516526, 0.71314, 0.50186676, 0.8944276, 0.5470671, 0.45485002, 0.82426745, 0.2785842,
+ 0.9404638, 0.8959508, 0.15114321, 0.18969482, 0.78833485, 0.9598267, 0.29174066, 0.3494771,
+ 0.5854956, 0.0831098, 0.960891, 0.56964827, 0.829203, 0.7542679, 0.9568423, 0.9578806,
+ 0.88932663, 0.48814714, 0.39864913, 0.42221805, 0.3055165, 0.42976233, 0.19865331, 0.93883455,
+ 0.7655661, 0.5970062, 0.4758167, 0.15800795, 0.17757647, 0.15753652, 0.3730905, 0.47599813,
+ 0.27207386, 0.42162967, 0.08353208, 0.96827507, 0.9347392, 0.51671463, 0.40915382, 0.7014796,
+ 0.35320777, 0.4194869, 0.3184117, 0.5446104, 0.81504035, 0.78465104, 0.9777143, 0.5973847,
+ 0.7562977, 0.54398614, 0.0051009622, 0.05891997, 0.05620089, 0.4020494, 0.9730677, 0.5107014,
+ 0.69729745, 0.21230865, 0.4241287, 0.19132863, 0.48401004, 0.1337327, 0.17190064, 0.42795905,
+ 0.7100193, 0.48489287, 0.29757443, 0.40757337, 0.67073584, 0.98856723, 0.023141444, 0.37261203,
+ 0.07899332, 0.6971695, 0.06901029, 0.8860296, 0.11135061, 0.65404296, 0.12379419, 0.98091507,
+ 0.6192919, 0.878432, 0.40171024, 0.63359034, 0.15243557, 0.31417054, 0.41979724, 0.87002444,
+ 0.44856197, 0.5728306, 0.2709776, 0.7224305, 0.09258589, 0.21782517, 0.21746957, 0.21947508,
+ 0.24758625, 0.8904527, 0.8345911, 0.3301475, 0.48707664, 0.57014096, 0.92664886, 0.7677305,
+ 0.5208447, 0.6324889, 0.97992665, 0.35903138, 0.3330391, 0.0870381, 0.39935082, 0.043254532,
+ 0.08851445, 0.44321367, 0.57203674, 0.60557806, 0.73202246, 0.5383103, 0.27552348, 0.39584875,
+ 0.06509563, 0.42754996, 0.95901144, 0.09790518, 0.7175897, 0.3007109, 0.28002614, 0.86116815,
+ 0.47969994, 0.8495352, 0.63844335, 0.22089794, 0.8194518, 0.7936467, 0.4938384, 0.049150985,
+ 0.9517831, 0.6339798, 0.11274567, 0.51994663, 0.3342439, 0.060765848, 0.53698534, 0.36152387,
+ 0.17347981, 0.22772305, 0.6339161, 0.6493722, 0.64578843, 0.6118915, 0.48745263, 0.70927596,
+ 0.6149292, 0.43874234, 0.26505187, 0.05952667, 0.6111295, 0.8287437, 0.050140806, 0.22013378,
+ 0.35246277, 0.1187585, 0.87933147, 0.4835039, 0.44859475, 0.1784529, 0.2238027, 0.29486778,
+ 0.9493753, 0.52288574, 0.65379494, 0.09804267, 0.42556462, 0.75557685, 0.061604857, 0.0043297815,
+ 0.8905646, 0.59748757, 0.92442536, 0.4898666, 0.6667948, 0.6306539, 0.21537969, 0.8678084,
+ 0.3620826, 0.9291674, 0.6059688, 0.3807095, 0.5285948, 0.43431175, 0.43802148, 0.123039424,
+ 0.583839, 0.8926119, 0.16748385, 0.2154854, 0.18143441, 0.05348144, 0.9129291, 0.99502695,
+ 0.003920352, 0.33904833, 0.69999695, 0.12290272, 0.9580966, 0.38940993, 0.2837113, 0.85935235,
+ 0.37713748, 0.2607221, 0.16896206, 0.013641968, 0.90431833, 0.5602742, 0.553339, 0.72180885,
+ 0.9033788, 0.011523027, 0.1214213, 0.51942736, 0.57248414, 0.8430932, 0.76627296, 0.5150635,
+ 0.084864266, 0.5307555, 0.51420367, 0.5329527, 0.588093, 0.84611946, 0.82289535, 0.83708316,
+ 0.68455845, 0.9293985, 0.48594627, 0.32774645, 0.930657, 0.092476964, 0.9097118, 0.97267264,
+ 0.6454561, 0.74661636, 0.003572011, 0.2678727, 0.2653497, 0.4243795, 0.2187211, 0.023564778,
+ 0.3392729, 0.44567502, 0.31210658, 0.16991138, 0.9320601, 0.39350176, 0.42254278, 0.16082714,
+ 0.57277536, 0.18493341, 0.03803846, 0.4273411, 0.87520623, 0.7507586, 0.27125937, 0.531018,
+ 0.43782672, 0.33187887, 0.32908353, 0.97491986, 0.07432794, 0.22559255, 0.7911518, 0.8109018,
+ 0.10181122, 0.14874865, 0.8739713, 0.8258678, 0.83952117, 0.49840027, 0.24971384, 0.6604848,
+ 0.3120344, 0.4906389, 0.19367984, 0.14241797, 0.5340129, 0.65298396, 0.90502304, 0.2910567,
+ 0.50685567, 0.3251191, 0.7549711, 0.7457236, 0.054438505, 0.4823707, 0.09746641, 0.8946975,
+ 0.47535703, 0.472554, 0.83004594, 0.9334708, 0.09529597, 0.24380124, 0.9492368, 0.11368034,
+ 0.6545232, 0.5012047, 0.06810016, 0.7833115, 0.5195305, 0.59667504, 0.32130596, 0.07437508,
+ 0.9352196, 0.3775537, 0.11530671, 0.38456735, 0.5570788, 0.12884142, 0.9970051, 0.7848427,
+ 0.42685586, 0.03802683, 0.4680642, 0.7492088, 0.47062147, 0.045428254, 0.75646335, 0.6194405,
+ 0.05128224, 0.9792738, 0.35051075, 0.3669672, 0.66835433, 0.31624305, 0.56518877, 0.06823316,
+ 0.5414021, 0.0799995, 0.4878948, 0.032808155, 0.5848838, 0.12171154, 0.7715262, 0.9101807,
+ 0.0038131434, 0.680596, 0.810504, 0.67688483, 0.36706397, 0.7128991, 0.3376187, 0.3465156,
+ 0.47554886, 0.04520323, 0.5066149, 0.05726915, 0.77573705, 0.200028, 0.6430589, 0.6090949,
+ 0.7447414, 0.44865963, 0.73202926, 0.5402566, 0.24616429, 0.9543388, 0.40602076, 0.61897653,
+ 0.8123649, 0.047073558, 0.8431653, 0.47707924, 0.6409466, 0.964197, 0.1999589, 0.3051443,
+ 0.2665006, 0.5578835, 0.7453957, 0.7900255, 0.23492423, 0.07957853, 0.25237653, 0.33838317,
+ 0.6416551, 0.0039951354, 0.89141834, 0.62315106, 0.80962807, 0.50791967, 0.29249611, 0.34137407,
+ 0.4369406, 0.8787999, 0.28806677, 0.1362242, 0.3896823, 0.23126958, 0.66401637, 0.049474377,
+ 0.27457523, 0.19152752, 0.8645199, 0.31999043, 0.8697338, 0.8605395, 0.70556897, 0.5113519,
+ 0.84524435, 0.20147063, 0.79076856, 0.21785353, 0.4546323, 0.8530334, 0.3741707, 0.66516286,
+ 0.1962831, 0.3936461, 0.89860153, 0.24216916, 0.062920436, 0.7828697, 0.8093484, 0.30444527,
+ 0.75457746, 0.5017912, 0.040138636, 0.7621467, 0.6761302, 0.06373471, 0.915462, 0.035231,
+ 0.89386714, 0.6959213, 0.51545024, 0.04339671, 0.21505861, 0.9323861, 0.46864936, 0.7811156,
+ 0.29842615, 0.38006642, 0.7779068, 0.60815746, 0.7171511, 0.07464257, 0.88674176, 0.5839072,
+ 0.5046292, 0.6229039, 0.9399411, 0.9960362, 0.33266804, 0.42184722, 0.9865539, 0.49170554,
+ 0.38217908, 0.5600747, 0.565413, 0.36794263, 0.82040083, 0.94342226, 0.8352217, 0.78150964,
+ 0.2860086, 0.75553757, 0.32398638, 0.758711, 0.3375832, 0.33077398, 0.45010427, 0.26389697,
+ 0.92499673, 0.11748593, 0.943743, 0.682854, 0.004962936, 0.20119096, 0.58729416, 0.67993486,
+ 0.6150494, 0.45623145, 0.25751752, 0.053226303, 0.12379362, 0.91942585, 0.702563, 0.47201994,
+ 0.7093674, 0.023744669, 0.66121763, 0.65498394, 0.36697313, 0.10070673, 0.96071476, 0.3550039,
+ 0.54484475, 0.99639714, 0.32214886, 0.96161354, 0.7506562, 0.12803078, 0.24632397, 0.17385522,
+ 0.17279965, 0.6760441, 0.071039446, 0.2151821, 0.4781042, 0.30369994, 0.48674262, 0.18098812,
+ 0.97278047, 0.8854781, 0.7528932, 0.3641694, 0.68590474, 0.7819954, 0.657716, 0.36658275,
+ 0.05297459, 0.85196644, 0.049343612, 0.31383854, 0.6695563, 0.7951203, 0.89692384, 0.82429004,
+ 0.15677115, 0.5887391, 0.13800927, 0.0085657975, 0.8790421, 0.6256806, 0.9292787, 0.48701864,
+ 0.20990747, 0.083662316, 0.88042665, 0.4477495, 0.8483864, 0.48738086, 0.99391574, 0.40566745,
+ 0.537002, 0.4802295, 0.6822035, 0.48149505, 0.34781352, 0.5965454, 0.66909915, 0.76284933,
+ 0.33868113, 0.9555661, 0.90863895, 0.89868975, 0.07868716, 0.93248546, 0.50429887, 0.37767935,
+ 0.77912027, 0.24674945, 0.05841095, 0.8893651, 0.16569066, 0.4781768, 0.301946, 0.34709984,
+ 0.9561994, 0.26587456, 0.15426192, 0.6022424, 0.9015687, 0.20996648, 0.51819634, 0.5655937,
+ 0.8580507, 0.64367616, 0.7768365, 0.18932684, 0.11291685, 0.4154288, 0.4764765, 0.5602257,
+ 0.91964, 0.37515992, 0.6698847, 0.923476, 0.7170417, 0.030588947, 0.40833148, 0.27742204,
+ 0.57936347, 0.5027473, 0.6686292, 0.60163695, 0.42896992, 0.10455062, 0.2399768, 0.058825243,
+ 0.17828348, 0.3351036, 0.5252956, 0.08193896, 0.44228348, 0.06685673, 0.8612806, 0.12871465,
+ 0.43736976, 0.34304523, 0.040639006, 0.435011, 0.15564895, 0.314972, 0.2647625, 0.36369145,
+ 0.770273, 0.4981852, 0.96972513, 0.79053074, 0.80829215, 0.37847006, 0.63005817, 0.9256105,
+ 0.85754305, 0.8768399, 0.022878975, 0.3988214, 0.54133725, 0.9165594, 0.1366238, 0.7535001,
+ 0.40369937, 0.71801126, 0.011043364, 0.77781326, 0.89013314, 0.39453754, 0.11794228, 0.85278326,
+ 0.5138793, 0.54117, 0.4861062, 0.37399647, 0.98994994, 0.9733205, 0.12177309, 0.26439142,
+ 0.23798482, 0.30493778, 0.83136404, 0.9307847, 0.13482551, 0.44944605, 0.25053307, 0.7998134,
+ 0.70504546, 0.5996852, 0.22439589, 0.5654436, 0.043977752, 0.4624592, 0.5873774, 0.52081037,
+ 0.20642142, 0.2871389, 0.031311635, 0.43763772, 0.30392867, 0.48694924, 0.4735583, 0.37573543,
+ 0.3802429, 0.11694187, 0.27665144, 0.26712215, 0.89236385, 0.25606167, 0.93566054, 0.8842226,
+ 0.7550668, 0.7584876, 0.16083659, 0.23639946, 0.08519537, 0.20583908, 0.6186746, 0.9542533,
+ 0.46747816, 0.21122995, 0.07276781, 0.29044798, 0.17014165, 0.5524987, 0.8088055, 0.0514201,
+ 0.9537926, 0.9652958, 0.16757506, 0.70281106, 0.94200885, 0.6841354, 0.96046275, 0.7510356,
+ 0.8313795, 0.45562857, 0.5505418, 0.017883644, 0.17279461, 0.9834109, 0.90744954, 0.44898376,
+ 0.66402465, 0.34017327, 0.81037676, 0.28549019, 0.3016226, 0.35097796, 0.43561503, 0.00058234343,
+ 0.6684643, 0.07705832, 0.97015953, 0.092698716, 0.41418144, 0.18311031, 0.20559378, 0.82774425,
+ 0.30813637, 0.22523133, 0.31332958, 0.92706805, 0.08848662, 0.23284948, 0.9422138, 0.07093142,
+ 0.7980248, 0.409801, 0.40501997, 0.6295668, 0.6552973, 0.600791, 0.7814587, 0.48406723,
+ 0.3037804, 0.62378407, 0.62642336, 0.82996833, 0.7421219, 0.5233153, 0.74979746, 0.6028146,
+ 0.5296808, 0.16699271, 0.03434674, 0.86495054, 0.71397585, 0.86776406, 0.33685416, 0.6482692,
+ 0.2500348, 0.7227976, 0.70974725, 0.9475633, 0.6700813, 0.9803815, 0.36049715, 0.43117517,
+ 0.39795953, 0.7394454, 0.4874654, 0.8918216, 0.94595796, 0.8060482, 0.3452851, 0.06767335,
+ 0.29559964, 0.4860923, 0.7889183, 0.7903974, 0.556687, 0.3756254, 0.08562232, 0.7848211,
+ 0.47543386, 0.71051496, 0.3973873, 0.9214939, 0.19850273, 0.07726323, 0.3569556, 0.9302608,
+ 0.072946854, 0.7567508, 0.37953198, 0.9324997, 0.89104366, 0.8338954, 0.8139859, 0.32339892,
+ 0.2632869, 0.19524816, 0.43200883, 0.002676534, 0.035849903, 0.8579759, 0.65685666, 0.7236325,
+ 0.82170767, 0.9666734, 0.5693509, 0.22788355, 0.07884572, 0.54645675, 0.09158218, 0.8744094,
+ 0.63717526, 0.9249262, 0.47212943, 0.9595664, 0.58299416, 0.43900326, 0.23267244, 0.3206963,
+ 0.3824898, 0.55720466, 0.8188748, 0.18920717, 0.42651626, 0.41278538, 0.17662966, 0.46170422,
+ 0.6721064, 0.4655194, 0.5271105, 0.3614388, 0.94361657, 0.08294579, 0.74897116, 0.617458,
+ 0.053658314, 0.67375475, 0.09978627, 0.23182935, 0.50791234, 0.12907204, 0.85141504, 0.5264901,
+ 0.66516864, 0.50512254, 0.29532441, 0.9661175, 0.36176598, 0.8544195, 0.7404047, 0.82428366,
+ 0.96257573, 0.11131253, 0.62018675, 0.47864527, 0.039101128, 0.46764946, 0.29711628, 0.40892226,
+ 0.7900437, 0.10764668, 0.55577713, 0.6133263, 0.019346252, 0.73014337, 0.9307928, 0.5542295,
+ 0.17595504, 0.8546715, 0.90590805, 0.9092394, 0.33921698, 0.0008430821, 0.81278396, 0.25341776,
+ 0.7057896, 0.29238465, 0.52403855, 0.9213937, 0.11746097, 0.21051219, 0.09993823, 0.8176869,
+ 0.72511464, 0.70282686, 0.3988631, 0.83230406, 0.46275905, 0.2703259, 0.57835686, 0.58600885,
+ 0.3766385, 0.690864, 0.44178563, 0.40026566, 0.5732949, 0.23808873, 0.50714386, 0.9350253,
+ 0.57432973, 0.74109495, 0.79016244, 0.5070945, 0.9485114, 0.8311653, 0.48506665, 0.9617326,
+ 0.29852858, 0.366769, 0.77285564, 0.74671644, 0.94361097, 0.3757226, 0.29146126, 0.57953155,
+ 0.007708449, 0.7380902, 0.88821167, 0.31651938, 0.33128026, 0.09848877, 0.09147043, 0.90562916,
+ 0.27631462, 0.31989923, 0.53260094, 0.648353, 0.5590575, 0.4125183, 0.68012285, 0.4677009,
+ 0.7852408, 0.5890133, 0.34706393, 0.37636602, 0.42034975, 0.5928437, 0.86917543, 0.89394933,
+ 0.21776019, 0.43713045, 0.5337755, 0.09599007, 0.49747026, 0.83164036, 0.6423979, 0.00091591524,
+ 0.39940274, 0.8622541, 0.3925572, 0.83520466, 0.3498771, 0.19062445, 0.603745, 0.475841,
+ 0.6496245, 0.8845333, 0.2307799, 0.6286122, 0.29856437, 0.83671373, 0.40267518, 0.8860103,
+ 0.6866461, 0.30515477, 0.9614757, 0.3545977, 0.028658632, 0.9150952, 0.15918177, 0.41486475,
+ 0.8689148, 0.9942623, 0.0987592, 0.8941498, 0.5647133, 0.99548036, 0.40815887, 0.44467425,
+ 0.6775013, 0.531685, 0.24895021, 0.69680333, 0.019961093, 0.8449182, 0.1178238, 0.59461635,
+ 0.98526824, 0.871223, 0.7267415, 0.53581643, 0.3620638, 0.24056326, 0.59538496, 0.38104647,
+ 0.034455262, 0.6477652, 0.40934396, 0.19231549, 0.8701647, 0.28780022, 0.97225726, 0.48430753,
+ 0.7030723, 0.9776925, 0.9662899, 0.3556148, 0.09186526, 0.7095952, 0.9111277, 0.65414417,
+ 0.47637445, 0.78610563, 0.9511109, 0.7668794, 0.5877635, 0.7058718, 0.8660492, 0.8417279,
+ 0.18733096, 0.3668593, 0.36932942, 0.15743567, 0.18835372, 0.62336534, 0.05280094, 0.6283515,
+ 0.3988773, 0.7177127, 0.85969454, 0.9169481, 0.5861364, 0.21584338, 0.5745095, 0.3897011,
+ 0.55942774, 0.7646427, 0.993731, 0.042268623, 0.8786283, 0.762209, 0.5027511, 0.27567303,
+ 0.9600953, 0.072597355, 0.059442017, 0.57595813, 0.2894524, 0.82850564, 0.793283, 0.32858342,
+ 0.78171605, 0.56761605, 0.0049845274, 0.50330544, 0.9184708, 0.8148216, 0.29595378, 0.07970701,
+ 0.92489153, 0.33793837, 0.9567375, 0.37415254, 0.84990066, 0.9941796, 0.06800775, 0.26053104,
+ 0.21159613, 0.5614098, 0.20745164, 0.8231208, 0.7121408, 0.82378054, 0.9630996, 0.42512196,
+ 0.8641082, 0.09365638, 0.19734041, 0.11575636, 0.5639233, 0.4768428, 0.33889914, 0.5703717,
+ 0.9244297, 0.5311111, 0.13523202, 0.01852037, 0.21085885, 0.071204096, 0.4712303, 0.74460614,
+ 0.4686889, 0.914024, 0.117377095, 0.54068995, 0.80547154, 0.12859856, 0.4257724, 0.9659156,
+ 0.0045896024, 0.798911, 0.36436203, 0.7280426, 0.621054, 0.9701622, 0.6164426, 0.9579355,
+ 0.6045164, 0.5798626, 0.63919723, 0.82481444, 0.61748123, 0.18019743, 0.5157837, 0.44804874,
+ 0.99903923, 0.3863658, 0.44972283, 0.31878954, 0.85894763, 0.049487386, 0.04967219, 0.14039204,
+ 0.09017946, 0.4628455, 0.3544319, 0.7981168, 0.70640343, 0.42240968, 0.6196504, 0.73550963,
+ 0.667884, 0.23142478, 0.11116676, 0.7650123, 0.112480775, 0.6108565, 0.9493177, 0.9542675,
+ 0.9146685, 0.17729652, 0.41400397, 0.6309963, 0.43200687, 0.6464159, 0.12712492, 0.2884915,
+ 0.3982403, 0.66932833, 0.54165065, 0.4191057, 0.67887574, 0.10698286, 0.10696802, 0.9551022,
+ 0.7492388, 0.22396998, 0.63786316, 0.15820846, 0.6157303, 0.8183258, 0.25153205, 0.18210672,
+ 0.9602121, 0.9036876, 0.15693043, 0.38605642, 0.06903067, 0.7507714, 0.33556795, 0.38818276,
+ 0.43704808, 0.4954553, 0.40412104, 0.6816511, 0.63548344, 0.4186759, 0.70838517, 0.44376358,
+ 0.3357206, 0.06594042, 0.39987648, 0.037075095, 0.88075906, 0.20054473, 0.05663389, 0.5609011,
+ 0.124456756, 0.15606454, 0.015773552, 0.88851076, 0.9729933, 0.79110926, 0.33853722, 0.09634267,
+ 0.9257645, 0.23189723, 0.6707842, 0.52831924, 0.48948547, 0.7410685, 0.2194608, 0.6474689,
+ 0.3337604, 0.15346791, 0.98205763, 0.18342042, 0.70286185, 0.42531693, 0.3196188, 0.3305629,
+ 0.5155848, 0.19409959, 0.82248783, 0.5497899, 0.41844934, 0.21445695, 0.3013477, 0.7596674,
+ 0.8470537, 0.5960293, 0.26159966, 0.91296613, 0.7349978, 0.44705716, 0.41518942, 0.6459388,
+ 0.1569181, 0.30777836, 0.7558866, 0.4035862, 0.7478917, 0.18006596, 0.9542781, 0.5946521,
+ 0.8464796, 0.75240755, 0.7033147, 0.7272911, 0.2184871, 0.87321347, 0.8580393, 0.69913983,
+ 0.83644575, 0.68521065, 0.372926, 0.77889377, 0.96862143, 0.7887473, 0.67789334, 0.7113075,
+ 0.93054956, 0.9111168, 0.6812655, 0.89345616, 0.47946882, 0.30649468, 0.9124711, 0.88670325,
+ 0.7382785, 0.33611885, 0.026502334, 0.39508346, 0.6694303, 0.9160326, 0.5826711, 0.33551884,
+ 0.23982148, 0.22783574, 0.70331025, 0.6660418, 0.51114225, 0.57405657, 0.5411803, 0.9738403,
+ 0.73799, 0.5624598, 0.07652036, 0.04978715, 0.07413118, 0.6362957, 0.6773174, 0.36817077,
+ 0.629885, 0.044579085, 0.47303665, 0.836775, 0.49880046, 0.06082195, 0.115183294, 0.53998494,
+ 0.83993644, 0.81661147, 0.98901266, 0.88236827, 0.84671116, 0.46295583, 0.029709496, 0.9204132,
+ 0.10253954, 0.03740714, 0.5390723, 0.74078566, 0.08543706, 0.011851499, 0.20016527, 0.356493,
+ 0.36993647, 0.70742524, 0.15546617, 0.917009, 0.22997431, 0.86268395, 0.81257206, 0.1019828,
+ 0.65880144, 0.6583316, 0.7651984, 0.6248512, 0.44299594, 0.74589616, 0.8367184, 0.17899951,
+ 0.11265245, 0.16332534, 0.8261054, 0.6945308, 0.5850439, 0.65881205, 0.12712914, 0.27503416,
+ 0.53275037, 0.15610719, 0.9472476, 0.036724042, 0.0972234, 0.9365317, 0.2827337, 0.6180335,
+ 0.8444138, 0.116543666, 0.46683854, 0.7913752, 0.9053558, 0.19817433, 0.3100106, 0.9772525,
+ 0.0040394296, 0.8870298, 0.22356682, 0.18837956, 0.6977574, 0.40485826, 0.47741726, 0.35664338,
+ 0.20068875, 0.36007276, 0.62813324, 0.92211175, 0.1857461, 0.5056345, 0.7714491, 0.7111244,
+ 0.5802961, 0.880432, 0.3842586, 0.07386713, 0.9154364, 0.775848, 0.0047594067, 0.7222697,
+ 0.37559786, 0.14716488, 0.7804374, 0.32645226, 0.27905762, 0.04534316, 0.27364373, 0.9144781,
+ 0.8533147, 0.84885293, 0.6904914, 0.6980141, 0.43524522, 0.93874955, 0.57727677, 0.1278921,
+ 0.67868996, 0.5906042, 0.8360353, 0.73715067, 0.30839851, 0.360622, 0.43228745, 0.33877933,
+ 0.3450946, 0.7557141, 0.21107915, 0.024923787, 0.8139157, 0.23614348, 0.061816096, 0.22819144,
+ 0.88227046, 0.5012971, 0.8127817, 0.55059254, 0.6244208, 0.15096499, 0.07758577, 0.15534559,
+ 0.08642902, 0.7136551, 0.068797, 0.33689317, 0.8151431, 0.073435, 0.27587917, 0.6415465,
+ 0.30315524, 0.25636652, 0.3951772, 0.32483214, 0.9398127, 0.26760876, 0.41387123, 0.014975904,
+ 0.7148774, 0.4416581, 0.9813577, 0.5233435, 0.83426404, 0.24871995, 0.100562416, 0.6171712,
+ 0.78703684, 0.4622999, 0.8157436, 0.93394816, 0.1259679, 0.026684225, 0.50347126, 0.527725,
+ 0.5130184, 0.6806897, 0.6507216, 0.59474343, 0.29182497, 0.09539426, 0.52363616, 0.27165958,
+ 0.47983494, 0.56953263, 0.72176856, 0.5575492, 0.8409663, 0.73698395, 0.28837872, 0.6146617,
+ 0.08742587, 0.7978058, 0.8357151, 0.18276273, 0.16960731, 0.55424225, 0.32108158, 0.83770907,
+ 0.61309266, 0.45162576, 0.54985636, 0.35284323, 0.25769138, 0.34193105, 0.5155786, 0.27647102,
+ 0.75289524, 0.86745226, 0.8118137, 0.259123, 0.61688715, 0.8191278, 0.7231509, 0.6194832,
+ 0.9180219, 0.7096981, 0.043508567, 0.26473138, 0.5269514, 0.5430132, 0.77620494, 0.05005288,
+ 0.1739212, 0.20108196, 0.8465223, 0.32816213, 0.19096912, 0.32070854, 0.35811764, 0.9587762,
+ 0.3596081, 0.81301254, 0.9816507, 0.84019923, 0.54553795, 0.17079297, 0.013968218, 0.13790388,
+ 0.053954035, 0.44529754, 0.80465394, 0.9735141, 0.92517024, 0.029255724, 0.99777454, 0.26829806,
+ 0.07465485, 0.21623193, 0.2647408, 0.45990923, 0.5107337, 0.056350194, 0.31075767, 0.07007945,
+ 0.6754208, 0.49980345, 0.17892201, 0.056609415, 0.4954088, 0.18741646, 0.08550189, 0.4321867,
+ 0.5093346, 0.85303754, 0.89951485, 0.8038746, 0.8374771, 0.88295174, 0.073945254, 0.7472289,
+ 0.69572985, 0.90560466, 0.21077734, 0.08165387, 0.7383593, 0.80269086, 0.12488264, 0.14466548,
+ 0.20330743, 0.5782242, 0.2535073, 0.9747372, 0.055967752, 0.8982084, 0.44804245, 0.30325794,
+ 0.50225484, 0.91157126, 0.16477837, 0.045734458, 0.99187094, 0.9573588, 0.6424951, 0.8665376,
+ 0.35979563, 0.37246728, 0.46417946, 0.0721327, 0.12974085, 0.19389993, 0.430821, 0.19170313,
+ 0.14228667, 0.51751184, 0.76417935, 0.605129, 0.8455728, 0.2291038, 0.3317202, 0.87272996,
+ 0.37492082, 0.034256544, 0.853302, 0.9171846, 0.9339092, 0.11076469, 0.37621894, 0.6111262,
+ 0.40499508, 0.5962569, 0.30161974, 0.92590576, 0.7181733, 0.028210793, 0.755358, 0.7383711,
+ 0.2631096, 0.34423977, 0.7218582, 0.365892, 0.3385114, 0.05274994, 0.014924624, 0.0094075035,
+ 0.1474032, 0.061804168, 0.8324505, 0.5384559, 0.13402902, 0.84291345, 0.45768508, 0.27315107,
+ 0.5798511, 0.29204842, 0.6708136, 0.9576144, 0.10405682, 0.7253105, 0.9326284, 0.24903095,
+ 0.99624836, 0.8530533, 0.6671376, 0.5334839, 0.8922802, 0.50491524, 0.47352976, 0.114075884,
+ 0.76215386, 0.025808325, 0.34201944, 0.50133306, 0.5072456, 0.9658282, 0.53421855, 0.32217088,
+ 0.019331919, 0.8438945, 0.7697814, 0.872105, 0.27831417, 0.837763, 0.47709718, 0.56208163,
+ 0.13857186, 0.028468672, 0.34605467, 0.42612493, 0.35739717, 0.79774356, 0.63431424, 0.5377991,
+ 0.4116114, 0.4728273, 0.36964366, 0.48545814, 0.3856123, 0.48144072, 0.11712731, 0.64248794,
+ 0.5882744, 0.71837467, 0.77630204, 0.1082207, 0.500894, 0.956352, 0.7659055, 0.6140229,
+ 0.75782984, 0.34864277, 0.9382825, 0.26016235, 0.9555291, 0.06052337, 0.9707168, 0.15848531,
+ 0.3759561, 0.10505597, 0.39491206, 0.86381155, 0.15886053, 0.047404833, 0.7566787, 0.96441025,
+ 0.3914941, 0.8042203, 0.08972167, 0.0344183, 0.59618455, 0.0487604, 0.93655854, 0.5378912,
+ 0.7267672, 0.12729345, 0.2838306, 0.5599395, 0.06146098, 0.3688765, 0.061187647, 0.18221985,
+ 0.2625632, 0.7320318, 0.6682951, 0.008754399, 0.85946107, 0.3741519, 0.58227, 0.35108802,
+ 0.5021105, 0.21115834, 0.10950206, 0.28055635, 0.08652866, 0.25331578, 0.48362744, 0.5408696,
+ 0.9616959, 0.8118918, 0.7167266, 0.6966737, 0.8666303, 0.73148715, 0.017838325, 0.7090695,
+ 0.4120842, 0.40039128, 0.5333952, 0.8282356, 0.77669275, 0.41077727, 0.09702433, 0.007079605,
+ 0.043868326, 0.21269222, 0.6012483, 0.42682874, 0.37910977, 0.7479243, 0.10494917, 0.01734221,
+ 0.22195028, 0.73863363, 0.5323078, 0.38502622, 0.93925834, 0.6560022, 0.45136255, 0.47345138,
+ 0.643666, 0.74296105, 0.5982436, 0.24956919, 0.65214986, 0.36451396, 0.31558952, 0.531076,
+ 0.71419346, 0.9592256, 0.5966702, 0.45906982, 0.8407567, 0.7540344, 0.5743953, 0.09133322,
+ 0.114134, 0.10242245, 0.23668802, 0.87383646, 0.6520674, 0.056798704, 0.16175981, 0.2137716,
+ 0.7069426, 0.6993844, 0.4747234, 0.1279967, 0.19917937, 0.6328121, 0.76981115, 0.756082,
+ 0.94902873, 0.059943788, 0.1845696, 0.03373171, 0.8125337, 0.84745514, 0.35492972, 0.67935437,
+ 0.8971027, 0.07017233, 0.7126353, 0.41988418, 0.15125412, 0.6458793, 0.1765855, 0.46791586,
+ 0.16423836, 0.4409746, 0.27089223, 0.83683586, 0.4193142, 0.5775261, 0.82138395, 0.58686733,
+ 0.58120126, 0.384472, 0.54262656, 0.95276546, 0.8897906, 0.1875928, 0.33189663, 0.08138137,
+ 0.18941447, 0.8405882, 0.51004106, 0.7808129, 0.5694648, 0.54066354, 0.27879953, 0.26667887,
+ 0.74749273, 0.55733365, 0.97673374, 0.5818951, 0.34416345, 0.74187565, 0.06251747, 0.061063267,
+ 0.5227989, 0.0068075284, 0.96375835, 0.75820476, 0.36191988, 0.93297523, 0.3367678, 0.37150264,
+ 0.23855984, 0.5977023, 0.45253047, 0.42806166, 0.30482855, 0.40216422, 0.7895638, 0.7095099,
+ 0.7382757, 0.6312539, 0.23046969, 0.3106659, 0.13583827, 0.39577258, 0.89845103, 0.6235748,
+ 0.16217506, 0.004213362, 0.08934315, 0.86198056, 0.60079235, 0.23948883, 0.24270387, 0.8393256,
+ 0.32195452, 0.4815633, 0.4299666, 0.8829831, 0.22383447, 0.57369184, 0.7194615, 0.2564392,
+ 0.5038204, 0.13853844, 0.5422531, 0.97176254, 0.0881331, 0.85073787, 0.9618503, 0.3453285,
+ 0.76776993, 0.26722383, 0.8436194, 0.7129096, 0.51140594, 0.75185156, 0.925225, 0.1270263,
+ 0.10835649, 0.34018353, 0.5960297, 0.35770652, 0.8436321, 0.47478724, 0.7707103, 0.999071,
+ 0.35499844, 0.6132049, 0.106107146, 0.82326525, 0.97219765, 0.9065807, 0.48567542, 0.16458383,
+ 0.9117924, 0.9740305, 0.8068454, 0.99729985, 0.8535195, 0.9266885, 0.5354417, 0.3114372,
+ 0.04236306, 0.7440147, 0.09421062, 0.3335685, 0.3958694, 0.52979434, 0.32791966, 0.57010293,
+ 0.5563383, 0.30294028, 0.77462655, 0.88365096, 0.97766215, 0.36175498, 0.41280714, 0.029033197,
+ 0.36782816, 0.5431821, 0.61676407, 0.47492823, 0.7446307, 0.13858505, 0.37313086, 0.86118925,
+ 0.7815484, 0.6790356, 0.8011172, 0.53737545, 0.94500613, 0.92792517, 0.27350682, 0.18166798,
+ 0.8047418, 0.2845925, 0.31534344, 0.09961744, 0.38057664, 0.43714178, 0.6032016, 0.82520413,
+ 0.28528523, 0.5360042, 0.26692694, 0.66925734, 0.13195412, 0.6020245, 0.18692169, 0.5500374,
+ 0.5612233, 0.77781224, 0.62947166, 0.31033742, 0.30992442, 0.060513485, 0.5668065, 0.903778,
+ 0.3708838, 0.2330214, 0.55202013, 0.71683383, 0.72867715, 0.79054415, 0.6250968, 0.62841314,
+ 0.029433481, 0.59295857, 0.07890911, 0.69306964, 0.046411548, 0.3131897, 0.6484566, 0.9306864,
+ 0.93998045, 0.79156, 0.189643, 0.20862652, 0.8716581, 0.7038735, 0.7292351, 0.1795239,
+ 0.49211392, 0.25107977, 0.9761521, 0.16719387, 0.29845348, 0.9631694, 0.87174356, 0.74422836,
+ 0.7177861, 0.41156542, 0.72873366, 0.14755523, 0.88512164, 0.8863678, 0.096526965, 0.49474105,
+ 0.9109074, 0.6385138, 0.63982385, 0.53899556, 0.5231154, 0.49385205, 0.5036258, 0.24803366,
+ 0.12935568, 0.6987853, 0.37035698, 0.5183644, 0.8708705, 0.35817996, 0.032119915, 0.66701025,
+ 0.5037863, 0.37249622, 0.22471993, 0.47759736, 0.81439203, 0.45790294, 0.32995966, 0.06626411,
+ 0.721215, 0.33468077, 0.97528356, 0.6348461, 0.584456, 0.50090134, 0.04556473, 0.053612676,
+ 0.695033, 0.69490194, 0.29771915, 0.23314431, 0.064049676, 0.19023955, 0.6564085, 0.99826187,
+ 0.7474539, 0.7281185, 0.037838195, 0.5996682, 0.5928124, 0.35337916, 0.87335783, 0.3596061,
+ 0.37944552, 0.06172341, 0.6437689, 0.51262546, 0.66164786, 0.6189296, 0.680349, 0.45300442,
+ 0.3085541, 0.57355976, 0.81778055, 0.18843463, 0.51856846, 0.8687797, 0.6635776, 0.6284543,
+ 0.6532206, 0.3167443, 0.8233314, 0.17596854, 0.06046078, 0.7989756, 0.6029606, 0.31354675,
+ 0.7160877, 0.22645807, 0.7301434, 0.086273566, 0.42006475, 0.7302915, 0.4734517, 0.36783585,
+ 0.4613229, 0.6156775, 0.2554006, 0.5227326, 0.8571324, 0.53293926, 0.39196482, 0.07610343,
+ 0.014552955, 0.84471476, 0.9245902, 0.49048993, 0.37245902, 0.4679739, 0.47969338, 0.8786742,
+ 0.06454086, 0.40938383, 0.9464476, 0.2760681, 0.5300478, 0.6973893, 0.2991453, 0.5804699,
+ 0.45876285, 0.33022216, 0.79653776, 0.43518978, 0.8887862, 0.59407544, 0.032939672, 0.5782626,
+ 0.10010804, 0.44994467, 0.7271117, 0.902891, 0.6133791, 0.140845, 0.77132195, 0.12028129,
+ 0.9247795, 0.74722797, 0.16141559, 0.21574605, 0.8743854, 0.11247064, 0.9410877, 0.24811381,
+ 0.74676466, 0.8514692, 0.021732707, 0.010680916, 0.7838439, 0.19738361, 0.8377881, 0.7639336,
+ 0.31653216, 0.6749307, 0.06396978, 0.52691025, 0.7364015, 0.956775, 0.18731725, 0.42047754,
+ 0.8117751, 0.34632754, 0.39038187, 0.9225143, 0.7408622, 0.57680243, 0.2652951, 0.92369586,
+ 0.6380619, 0.82616633, 0.35128862, 0.7828198, 0.5359737, 0.08339928, 0.7060845, 0.3462922,
+ 0.38913444, 0.54842395, 0.6884251, 0.037316978, 0.5723427, 0.022258755, 0.79441875, 0.90272444,
+ 0.61215657, 0.9631781, 0.5863588, 0.9384484, 0.07687521, 0.24441172, 0.38387978, 0.96800447,
+ 0.5599107, 0.74093807, 0.403971, 0.5280579, 0.72208875, 0.018573398, 0.5072516, 0.16996226,
+ 0.58617413, 0.09803684, 0.37261903, 0.95767754, 0.84609497, 0.05496832, 0.22795987, 0.23313288,
+ 0.9688462, 0.7176776, 0.1377758, 0.18797757, 0.26834992, 0.15000027, 0.8481348, 0.7895163,
+ 0.5519088, 0.48765746, 0.31035778, 0.77768403, 0.9904436, 0.32684666, 0.84682065, 0.39365014,
+ 0.44228655, 0.38328415, 0.22290905, 0.79503566, 0.6794283, 0.17802662, 0.62420344, 0.37056103,
+ 0.041172326, 0.51846284, 0.45114288, 0.47430587, 0.6496397, 0.8367412, 0.05662944, 0.5571883,
+ 0.7352182, 0.35322595, 0.9696022, 0.35919765, 0.10663593, 0.19590221, 0.6996546, 0.40991047,
+ 0.89280325, 0.6144547, 0.9761491, 0.23443131, 0.70821565, 0.7295676, 0.17951865, 0.25932744,
+ 0.25121617, 0.97896886, 0.515391, 0.46281084, 0.83205926, 0.4329242, 0.55370456, 0.7908196,
+ 0.093474135, 0.7672148, 0.14680524, 0.74988705, 0.69885737, 0.37382892, 0.13987659, 0.7151676,
+ 0.431028, 0.75316954, 0.04246583, 0.63721764, 0.35724443, 0.48762304, 0.28701422, 0.24638435,
+ 0.6836296, 0.8129986, 0.9022324, 0.064973645, 0.20187753, 0.38977212, 0.6623454, 0.31160477,
+ 0.3389442, 0.19181544, 0.2230897, 0.6706708, 0.32135025, 0.5938186, 0.725129, 0.30229402,
+ 0.7995213, 0.17878264, 0.2657235, 0.33942115, 0.04909697, 0.94976753, 0.7110531, 0.5189743,
+ 0.47457805, 0.2609815, 0.8034033, 0.9550461, 0.6871017, 0.542301, 0.90208304, 0.76359314,
+ 0.6919547, 0.2690066, 0.77918124, 0.019060668, 0.5306918, 0.48873094, 0.58894205, 0.703702,
+ 0.104869366, 0.8352005, 0.41094282, 0.507042, 0.15073924, 0.46920577, 0.3938173, 0.8372094,
+ 0.028040525, 0.7401718, 0.8376963, 0.17846179, 0.22189952, 0.9475931, 0.19728738, 0.7338621,
+ 0.101945534, 0.3832581, 0.59039557, 0.94089603, 0.5863688, 0.7072993, 0.624503, 0.7966432,
+ 0.28973243, 0.45949653, 0.9787162, 0.052343633, 0.81463736, 0.70606834, 0.7716022, 0.31079042,
+ 0.5898406, 0.5620215, 0.23455179, 0.21389648, 0.5388247, 0.2040111, 0.36823508, 0.0053723096,
+ 0.8671642, 0.9661939, 0.9270056, 0.94692993, 0.7046047, 0.72362125, 0.5416936, 0.7443616,
+ 0.07171923, 0.04531915, 0.91711515, 0.1474337, 0.89833534, 0.648046, 0.11733318, 0.39757007,
+ 0.21069747, 0.6142996, 0.21730955, 0.6912427, 0.49048957, 0.34147367, 0.022572042, 0.3219722,
+ 0.9685696, 0.5269059, 0.5886212, 0.659878, 0.7130413, 0.98339087, 0.19503741, 0.89793444,
+ 0.015023004, 0.5850233, 0.07373183, 0.62017494, 0.7802937, 0.6775731, 0.09203854, 0.5661112,
+ 0.9178029, 0.2343546, 0.9806244, 0.7693182, 0.7889532, 0.6241685, 0.41245508, 0.9417946,
+ 0.44468832, 0.8369817, 0.0031990237, 0.9245251, 0.98670155, 0.6769924, 0.51488274, 0.5256905,
+ 0.9436219, 0.6050334, 0.97836035, 0.17769879, 0.13500004, 0.8818156, 0.0313203, 0.08832834,
+ 0.8502817, 0.019180698, 0.13241069, 0.31331208, 0.5743142, 0.49715826, 0.6172764, 0.5331244,
+ 0.5222611, 0.6511984, 0.7734398, 0.256135, 0.3608493, 0.25325385, 0.533019, 0.34440103,
+ 0.114450805, 0.6468266, 0.2151897, 0.8760596, 0.9801919, 0.27051234, 0.9112329, 0.3380306,
+ 0.07014053, 0.54804134, 0.6765531, 0.1752603, 0.69921273, 0.9143398, 0.43111116, 0.035987273,
+ 0.2030343, 0.8922961, 0.91903645, 0.76977247, 0.49175784, 0.099143006, 0.3674804, 0.94753003,
+ 0.21970531, 0.47007462, 0.40226397, 0.3355032, 0.9035526, 0.25874776, 0.16484123, 0.69036806,
+ 0.07201438, 0.63395935, 0.063247986, 0.48817343, 0.6666259, 0.15526073, 0.10813647, 0.5797694,
+ 0.10794782, 0.79438007, 0.24317154, 0.026272861, 0.8206052, 0.4420161, 0.8339117, 0.6079213,
+ 0.22008722, 0.73745257, 0.053100668, 0.46855322, 0.33421737, 0.76324654, 0.8526432, 0.015307797,
+ 0.27934623, 0.26765963, 0.65635425, 0.51011723, 0.86824834, 0.57572967, 0.43447804, 0.8113928,
+ 0.38320008, 0.986185, 0.10324592, 0.06525337, 0.85109174, 0.94293773, 0.36936134, 0.047773577,
+ 0.7841596, 0.33926708, 0.66182464, 0.69737774, 0.85597146, 0.34120753, 0.12692484, 0.7776892,
+ 0.63616294, 0.79434264, 0.11541597, 0.16610004, 0.2056471, 0.696288, 0.35615066, 0.30876786,
+ 0.78131616, 0.04794019, 0.2088272, 0.39896628, 0.49890646, 0.59801924, 0.711521, 0.5322181,
+ 0.35990205, 0.43177876, 0.6430728, 0.8344202, 0.33877015, 0.76865834, 0.75682956, 0.2771495,
+ 0.3680912, 0.005327093, 0.68439364, 0.9949503, 0.10142185, 0.15526544, 0.15933633, 0.9381387,
+ 0.14073479, 0.87866503, 0.8739543, 0.07390571, 0.46031374, 0.268378, 0.6057457, 0.68691206,
+ 0.6300343, 0.79447806, 0.28393722, 0.80315155, 0.73411053, 0.9703951, 0.5488671, 0.18614037,
+ 0.6277461, 0.12960654, 0.33747572, 0.4241927, 0.6981348, 0.29250467, 0.43891907, 0.8675046,
+ 0.037513115, 0.8382665, 0.79800886, 0.20032, 0.011894401, 0.3612004, 0.207346, 0.6260507,
+ 0.88860387, 0.27068847, 0.25823146, 0.62024146, 0.72406495, 0.6376153, 0.0719044, 0.09152406,
+ 0.82603306, 0.9561607, 0.20438583, 0.5442921, 0.4847211, 0.95367795, 0.54303896, 0.3976961,
+ 0.45646, 0.49825326, 0.3672042, 0.9718153, 0.81778973, 0.73514366, 0.24000394, 0.8482301,
+ 0.43974596, 0.006449677, 0.036392592, 0.62204725, 0.47036913, 0.4054257, 0.67501765, 0.26883397,
+ 0.58713204, 0.6578865, 0.91454774, 0.46342203, 0.7121636, 0.92862564, 0.46207544, 0.9901308,
+ 0.057702154, 0.24595165, 0.5981596, 0.74197406, 0.08811883, 0.894627, 0.38278353, 0.08383514,
+ 0.2952275, 0.40031275, 0.74386, 0.5136412, 0.9939962, 0.2355307, 0.808261, 0.15346022,
+ 0.030684536, 0.41000134, 0.1804955, 0.71761525, 0.6012227, 0.44985715, 0.6211549, 0.4206074,
+ 0.28114304, 0.9355519, 0.95716006, 0.82683456, 0.03913026, 0.07961693, 0.6855325, 0.52783436,
+ 0.036177807, 0.3770734, 0.91411316, 0.5718381, 0.13698402, 0.4980299, 0.76011133, 0.545119,
+ 0.62366617, 0.95255744, 0.32681978, 0.07005637, 0.66156566, 0.16137652, 0.27483776, 0.35160136,
+ 0.8496255, 0.7610875, 0.4327375, 0.30216226, 0.74813014, 0.74446017, 0.38890806, 0.607845,
+ 0.62479675, 0.17755221, 0.46083102, 0.15256695, 0.9374669, 0.5559489, 0.04470488, 0.21561056,
+ 0.7147803, 0.21602567, 0.47746333, 0.6169228, 0.32141757, 0.23642296, 0.016476203, 0.53265464,
+ 0.64989, 0.6353765, 0.0939491, 0.64866525, 0.12303737, 0.5510985, 0.7590417, 0.11976651,
+ 0.6607141, 0.6055587, 0.9772091, 0.27804276, 0.64687943, 0.38337022, 0.7797042, 0.29171762,
+ 0.9881654, 0.30626813, 0.94704133, 0.9594318, 0.037198868, 0.60754436, 0.60765207, 0.06771721,
+ 0.9078526, 0.1112092, 0.3552761, 0.44554, 0.6839132, 0.657915, 0.030183792, 0.6132026,
+ 0.74461126, 0.9000829, 0.6522722, 0.112753615, 0.6505111, 0.74024284, 0.48480767, 0.073698185,
+ 0.4185105, 0.3410645, 0.49185285, 0.33190826, 0.5787399, 0.7666621, 0.5687311, 0.33141005,
+ 0.43632144, 0.18574573, 0.6287574, 0.01514944, 0.28938162, 0.057044394, 0.49545577, 0.042345677,
+ 0.027724478, 0.026231889, 0.74081266, 0.011828165, 0.19582245, 0.31350172, 0.43585333, 0.0027991086,
+ 0.5753749, 0.36400652, 0.5334315, 0.74679655, 0.731098, 0.6669506, 0.6412065, 0.24792254,
+ 0.8214605, 0.8733431, 0.54092133, 0.6961343, 0.115691505, 0.27574378, 0.48897734, 0.14119047,
+ 0.5424781, 0.02386607, 0.009218562, 0.49816743, 0.029157575, 0.015034353, 0.32382092, 0.6875669,
+ 0.40462708, 0.6099266, 0.08502913, 0.6242792, 0.9994301, 0.4729795, 0.87787575, 0.10500878,
+ 0.90521115, 0.48905376, 0.7565334, 0.21473333, 0.23323065, 0.8219346, 0.60031205, 0.76937085,
+ 0.5445392, 0.38083488, 0.19368897, 0.41603848, 0.51612306, 0.7993214, 0.92665416, 0.75198066,
+ 0.5372545, 0.5996222, 0.4693501, 0.17195638, 0.30428314, 0.9376859, 0.9736415, 0.5603405,
+ 0.040185597, 0.8458646, 0.34216946, 0.12117143, 0.58192146, 0.016927328, 0.24849239, 0.34848097,
+ 0.99546736, 0.43591255, 0.7909232, 0.62663776, 0.51921046, 0.274244, 0.9079598, 0.72054344,
+ 0.42355403, 0.2398477, 0.95362824, 0.6483227, 0.8213454, 0.90778244, 0.17144382, 0.6053057,
+ 0.68327236, 0.33304846, 0.08702466, 0.39980793, 0.0036293846, 0.7059194, 0.80072564, 0.96752524,
+ 0.5154122, 0.19619283, 0.17454775, 0.38736606, 0.47976512, 0.4791406, 0.1874494, 0.52761185,
+ 0.13234249, 0.845208, 0.4205711, 0.08021053, 0.00839825, 0.3000164, 0.23277025, 0.26301053,
+ 0.6916624, 0.74880666, 0.74840236, 0.064435445, 0.98405766, 0.32531884, 0.73899513, 0.13240317,
+ 0.6744208, 0.7368638, 0.43789902, 0.24887301, 0.9299027, 0.8486845, 0.34485158, 0.289548,
+ 0.6351869, 0.82339793, 0.11122555, 0.3230176, 0.09969627, 0.52059376, 0.24077836, 0.9444134,
+ 0.05239831, 0.42601636, 0.5159802, 0.9761374, 0.48721132, 0.09123329, 0.59690744, 0.383256,
+ 0.1002782, 0.8240141, 0.70814556, 0.25482276, 0.957517, 0.7362902, 0.9834676, 0.19009337,
+ 0.45719767, 0.042144574, 0.71294534, 0.7429013, 0.041241586, 0.9385764, 0.59770924, 0.28365803,
+ 0.50035644, 0.13102308, 0.44502363, 0.18500035, 0.18879086, 0.90975267, 0.16331425, 0.17106864,
+ 0.50802827, 0.80398893, 0.012037134, 0.55804133, 0.8093386, 0.7628578, 0.64519185, 0.58318746,
+ 0.1399564, 0.05464305, 0.14859481, 0.10588853, 0.14053893, 0.09002884, 0.332031, 0.89889675,
+ 0.8399303, 0.9211322, 0.86581993, 0.057551697, 0.8076484, 0.49787706, 0.90317184, 0.113821924,
+ 0.82830715, 0.23232217, 0.47578096, 0.35618824, 0.64620966, 0.41190708, 0.19446513, 0.19052555,
+ 0.6606999, 0.5370769, 0.74679446, 0.15352806, 0.72425306, 0.42542627, 0.3807547, 0.6943399,
+ 0.39695272, 0.12975785, 0.6029449, 0.98659855, 0.78998154, 0.4918207, 0.1431191, 0.41032755,
+ 0.7989921, 0.5461269, 0.34507003, 0.26765865, 0.043932725, 0.105762556, 0.36342022, 0.010151213,
+ 0.90081716, 0.89821523, 0.7297342, 0.5770165, 0.2870768, 0.28900358, 0.9369778, 0.72804934,
+ 0.86017793, 0.95806926, 0.44518864, 0.60346204, 0.34323436, 0.17850293, 0.17464367, 0.41450405,
+ 0.5403775, 0.17148003, 0.660599, 0.6778906, 0.89493215, 0.9165733, 0.32384035, 0.33648646,
+ 0.08920308, 0.06545341, 0.5571962, 0.10008278, 0.06683705, 0.92680645, 0.14659283, 0.5549373,
+ 0.17365667, 0.73664325, 0.25271094, 0.8260378, 0.69569206, 0.80373824, 0.4072631, 0.10794914,
+ 0.19278006, 0.8748956, 0.12642062, 0.8319123, 0.04663203, 0.53965706, 0.06709321, 0.6204891,
+ 0.37148324, 0.93056595, 0.7272812, 0.8724527, 0.44516358, 0.68552965, 0.11521906, 0.98424387,
+ 0.57437485, 0.39324772, 0.48781338, 0.22162339, 0.7318074, 0.836895, 0.66121227, 0.9333714,
+ 0.81147647, 0.89025134, 0.42980537, 0.6065911, 0.925792, 0.3486058, 0.718812, 0.7366392,
+ 0.7642169, 0.55264986, 0.4851105, 0.02003657, 0.79015267, 0.49192804, 0.28985444, 0.54954606,
+ 0.9983602, 0.936707, 0.72859955, 0.13627109, 0.1995253, 0.27414012, 0.10977373, 0.48812705,
+ 0.6214242, 0.26846707, 0.251663, 0.30244434, 0.31592485, 0.18563971, 0.3761417, 0.35588506,
+ 0.2136833, 0.19304918, 0.020435851, 0.1563807, 0.10985168, 0.46050212, 0.69469714, 0.022877397,
+ 0.211754, 0.99064195, 0.10823577, 0.89251375, 0.20041913, 0.09518249, 0.19409119, 0.082446806,
+ 0.1033933, 0.93826735, 0.22326319, 0.7951004, 0.108295456, 0.5249412, 0.7338461, 0.53733635,
+ 0.7804776, 0.94167835, 0.9851669, 0.6573249, 0.09694284, 0.41636762, 0.42071435, 0.5785772,
+ 0.17650813, 0.12922545, 0.8063533, 0.5971035, 0.4714922, 0.13347372, 0.43969434, 0.53785807,
+ 0.2420099, 0.70572215, 0.9245171, 0.20888333, 0.16590436, 0.21725997, 0.2877079, 0.5262417,
+ 0.07437589, 0.16921617, 0.19905105, 0.3776575, 0.96237653, 0.58104134, 0.2475896, 0.6887421,
+ 0.459203, 0.48309952, 0.3759031, 0.16817336, 0.47533524, 0.037372224, 0.92593455, 0.7953864,
+ 0.5699276, 0.52965856, 0.7160056, 0.07119369, 0.28882924, 0.5969877, 0.6109546, 0.96991956,
+ 0.498573, 0.68540514, 0.5530905, 0.40257332, 0.6004241, 0.52496284, 0.37143198, 0.56321764,
+ 0.6539704, 0.45892516, 0.58294904, 0.9277267, 0.21731657, 0.043056846, 0.6162007, 0.5954668,
+ 0.88163584, 0.11761114, 0.13790047, 0.98839265, 0.7575706, 0.271521, 0.06252285, 0.20463766,
+ 0.7797876, 0.1291307, 0.6389557, 0.6362458, 0.5012543, 0.21651421, 0.23741248, 0.4773882,
+ 0.5582616, 0.22913149, 0.8790845, 0.27697143, 0.02795082, 0.8450163, 0.08831802, 0.9342402,
+ 0.11166756, 0.8126855, 0.51420295, 0.016410068, 0.4544232, 0.99820787, 0.5780698, 0.5268707,
+ 0.9134579, 0.12053883, 0.18955784, 0.1712181, 0.45908722, 0.62256193, 0.21234894, 0.227052,
+ 0.62288225, 0.34845284, 0.6227857, 0.4712934, 0.8860071, 0.73518616, 0.06196327, 0.4374562,
+ 0.22151268, 0.10556084, 0.3694651, 0.9881851, 0.16397232, 0.3392293, 0.56751597, 0.036619555,
+ 0.029293122, 0.20366028, 0.87672514, 0.94488513, 0.757318, 0.04611278, 0.75021446, 0.78157973,
+ 0.5510609, 0.112084985, 0.7227879, 0.38071552, 0.026956385, 0.0661944, 0.01830097, 0.93569964,
+ 0.016782548, 0.6520325, 0.65408915, 0.67949796, 0.22223058, 0.6170246, 0.048233118, 0.37648138,
+ 0.7507222, 0.07674675, 0.7948974, 0.34886235, 0.6287428, 0.5898847, 0.36289844, 0.5742286,
+ 0.55302286, 0.15293828, 0.14192496, 0.25542694, 0.74583685, 0.26746377, 0.46973395, 0.5767695,
+ 0.59823835, 0.841206, 0.9202325, 0.7739221, 0.012398226, 0.6812478, 0.4104998, 0.15531828,
+ 0.087259874, 0.43376547, 0.9714025, 0.5119398, 0.68514013, 0.888018, 0.814389, 0.4122685,
+ 0.15542716, 0.5002437, 0.19416295, 0.6805713, 0.2512154, 0.4013521, 0.15283692, 0.96117616,
+ 0.7491866, 0.14855935, 0.8276927, 0.8740181, 0.92426944, 0.762874, 0.18986279, 0.7493188,
+ 0.18229857, 0.07731968, 0.08125962, 0.3810246, 0.6967921, 0.27431104, 0.36408317, 0.06947445,
+ 0.66624695, 0.6395791, 0.2616025, 0.19497731, 0.6184822, 0.85095865, 0.88908845, 0.66500485,
+ 0.33854932, 0.72965646, 0.099999785, 0.24559312, 0.07330083, 0.78916264, 0.32555407, 0.19688624,
+ 0.6883691, 0.9590563, 0.024735536, 0.86383885, 0.8535551, 0.53648174, 0.23104885, 0.32438585,
+ 0.24390268, 0.22208378, 0.32964125, 0.60782045, 0.8067584, 0.4333644, 0.71547633, 0.88111615,
+ 0.13616055, 0.1246885, 0.014324361, 0.6116363, 0.13974965, 0.9578596, 0.34269398, 0.89822793,
+ 0.25947088, 0.16268782, 0.53546876, 0.19461296, 0.6628742, 0.94426966, 0.67601794, 0.3931359,
+ 0.7517656, 0.88437337, 0.6926555, 0.7377358, 0.2495755, 0.50024426, 0.21591938, 0.12976523,
+ 0.40853027, 0.93721664, 0.95107466, 0.39639843, 0.52131736, 0.28126806, 0.85824645, 0.9051849,
+ 0.01418011, 0.21888365, 0.10943257, 0.94861233, 0.77483827, 0.7139178, 0.057136595, 0.73050946,
+ 0.61636233, 0.1265076, 0.60436803, 0.69086725, 0.0010129241, 0.036435887, 0.6615116, 0.299633,
+ 0.54606587, 0.9365053, 0.85605484, 0.922385, 0.7407089, 0.9777405, 0.63154066, 0.63591623,
+ 0.90876913, 0.88455915, 0.20310602, 0.20253302, 0.0067849625, 0.94629556, 0.37691054, 0.9782028,
+ 0.30444136, 0.63028383, 0.18043286, 0.4439906, 0.8348371, 0.7274056, 0.61829764, 0.037847787,
+ 0.8272368, 0.96214604, 0.12137349, 0.123067886, 0.8958763, 0.52505213, 0.1287523, 0.3720944,
+ 0.275705, 0.65144163, 0.85033256, 0.58481205, 0.42521322, 0.93586147, 0.16447607, 0.036439568,
+ 0.58734304, 0.47351632, 0.039843205, 0.8902792, 0.5108118, 0.8546036, 0.72372454, 0.6700668,
+ 0.7495971, 0.6261652, 0.3864259, 0.3707291, 0.85600305, 0.21752104, 0.4647959, 0.81866026,
+ 0.3182077, 0.818207, 0.09514821, 0.77856284, 0.85636705, 0.50847274, 0.74004, 0.38371703,
+ 0.7558068, 0.83101165, 0.926828, 0.35534334, 0.09596299, 0.7920985, 0.5529896, 0.36857986,
+ 0.46580777, 0.14399329, 0.85664755, 0.3613208, 0.6875624, 0.72801846, 0.527036, 0.9726332,
+ 0.23842148, 0.45130673, 0.37347084, 0.26971108, 0.1386262, 0.7580232, 0.51609135, 0.058183976,
+ 0.18664573, 0.031672336, 0.26660433, 0.6070062, 0.84071326, 0.38591322, 0.18007252, 0.07887025,
+ 0.73347634, 0.6561262, 0.13447234, 0.67980015, 0.92777556, 0.3683812, 0.5741038, 0.95749855,
+ 0.07317559, 0.017846042, 0.9049213, 0.7120097, 0.36087346, 0.10347511, 0.13109785, 0.5901893,
+ 0.29117107, 0.12251501, 0.54014134, 0.40506032, 0.13500193, 0.4703289, 0.24509083, 0.9977836,
+ 0.3149203, 0.868644, 0.16869761, 0.06429065, 0.52549416, 0.94598347, 0.5278666, 0.079894565,
+ 0.9639208, 0.7777773, 0.62784445, 0.0314362, 0.5935461, 0.8472358, 0.04485763, 0.8700403,
+ 0.8772029, 0.4159723, 0.1965355, 0.120780155, 0.8531019, 0.80408156, 0.6973105, 0.08317062,
+ 0.9005745, 0.6764151, 0.3158351, 0.71819824, 0.84577185, 0.7750122, 0.94386834, 0.26314744,
+ 0.41103536, 0.13668874, 0.36487988, 0.059131548, 0.19968359, 0.50981313, 0.4320044, 0.12719214,
+ 0.48997945, 0.82502675, 0.74808896, 0.58309615, 0.47563064, 0.09966165, 0.9966431, 0.44393525,
+ 0.07765738, 0.67010105, 0.5278574, 0.71902966, 0.27379337, 0.12431067, 0.14468168, 0.5108387,
+ 0.1713335, 0.08552699, 0.16371617, 0.8490791, 0.63014835, 0.80966836, 0.23412272, 0.18890859,
+ 0.833909, 0.364697, 0.62040085, 0.45685738, 0.48235595, 0.98572606, 0.6703567, 0.3673898,
+ 0.9839679, 0.06934336, 0.6308007, 0.02807519, 0.0559926, 0.11421437, 0.60753995, 0.80091286,
+ 0.67977196, 0.87189984, 0.6405409, 0.17567077, 0.24715477, 0.22483869, 0.9893541, 0.2867247,
+ 0.9920071, 0.85404116, 0.887798, 0.114156604, 0.34609696, 0.5829253, 0.49704382, 0.6803111,
+ 0.590904, 0.5591804, 0.7491872, 0.110933654, 0.4792608, 0.53978574, 0.9615793, 0.091931306,
+ 0.99974436, 0.1604676, 0.73506176, 0.20445003, 0.49350995, 0.11660648, 0.4548461, 0.057119142,
+ 0.47798702, 0.36280334, 0.16930713, 0.7582485, 0.16912746, 0.058451943, 0.9417538, 0.6090703,
+ 0.37534294, 0.33367616, 0.4648503, 0.6283148, 0.09792804, 0.5562001, 0.021292835, 0.40104258,
+ 0.57229954, 0.95048964, 0.4371712, 0.49681222, 0.36502722, 0.49660632, 0.32165202, 0.13998619,
+ 0.9103205, 0.54860955, 0.17592642, 0.086687185, 0.48977694, 0.78490406, 0.79321474, 0.8754006,
+ 0.39919505, 0.8306789, 0.63616955, 0.98329365, 0.41361818, 0.73879534, 0.5111836, 0.53245205,
+ 0.6174266, 0.14011684, 0.7355907, 0.14558467, 0.074935436, 0.33326453, 0.99400324, 0.44354424,
+ 0.13917476, 0.33401918, 0.6321505, 0.5430203, 0.6794353, 0.9580339, 0.69209194, 0.9813807,
+ 0.041151315, 0.029320937, 0.8479279, 0.6205179, 0.8825255, 0.85506666, 0.11929336, 0.5904389,
+ 0.5404614, 0.58944976, 0.22911972, 0.26724914, 0.92003053, 0.037999198, 0.9874244, 0.83350426,
+ 0.439306, 0.9047191, 0.87938565, 0.22491038, 0.7610156, 0.17606735, 0.06505076, 0.577056,
+ 0.5546063, 0.7323822, 0.94751245, 0.15575777, 0.15275358, 0.2501944, 0.19596528, 0.44116116,
+ 0.13858697, 0.65478885, 0.9421423, 0.38429725, 0.89086735, 0.8906657, 0.64992654, 0.7623599,
+ 0.020823486, 0.14515182, 0.6051233, 0.4854857, 0.10414482, 0.7267541, 0.52351373, 0.10117556,
+ 0.34659478, 0.7986462, 0.10371433, 0.7747162, 0.078648254, 0.46718153, 0.22036512, 0.86508393,
+ 0.9642702, 0.27087194, 0.06591158, 0.15014334, 0.9075542, 0.9635356, 0.4376853, 0.290267,
+ 0.39348447, 0.78795856, 0.12866218, 0.26524165, 0.095856875, 0.6031271, 0.94263685, 0.54864025,
+ 0.25479257, 0.11702571, 0.20408688, 0.6158638, 0.5709441, 0.57956505, 0.47291118, 0.8278522,
+ 0.20886846, 0.8463369, 0.809163, 0.35410735, 0.14648008, 0.4212491, 0.36251292, 0.67140543,
+ 0.43442374, 0.07705836, 0.42002708, 0.6199954, 0.8247542, 0.4997832, 0.8548057, 0.057287898,
+ 0.7074665, 0.31485626, 0.09200123, 0.31618625, 0.59809196, 0.25827205, 0.0053186826, 0.7434676,
+ 0.85600936, 0.5550741, 0.5199236, 0.96162254, 0.26309466, 0.60450137, 0.29413986, 0.38470513,
+ 0.79796076, 0.23805939, 0.9412749, 0.061217327, 0.15437259, 0.083577976, 0.14378692, 0.9722354,
+ 0.42544565, 0.45725676, 0.8308179, 0.018798511, 0.18310007, 0.32264143, 0.72388613, 0.75500935,
+ 0.26221997, 0.146799, 0.90839726, 0.25608784, 0.48756382, 0.15672493, 0.22976026, 0.9505964,
+ 0.8410182, 0.06569535, 0.498098, 0.591406, 0.90132546, 0.40089035, 0.40831077, 0.82992244,
+ 0.7829185, 0.03532195, 0.8220347, 0.5866948, 0.55850834, 0.7935884, 0.9029153, 0.62388855,
+ 0.17106935, 0.11976584, 0.8907406, 0.14083518, 0.42745417, 0.9865202, 0.5603676, 0.53336793,
+ 0.83118796, 0.7649143, 0.6994026, 0.116295666, 0.69610405, 0.03805204, 0.8971413, 0.6412358,
+ 0.008299126, 0.9906785, 0.22019914, 0.08867724, 0.58548, 0.5523809, 0.07090994, 0.024555296,
+ 0.048945986, 0.0008954834, 0.23588002, 0.14777812, 0.5006067, 0.13719136, 0.19650105, 0.46863157,
+ 0.24388368, 0.28450873, 0.08501847, 0.367798, 0.26598433, 0.08892508, 0.5231422, 0.854498,
+ 0.50532776, 0.96473, 0.760218, 0.13641119, 0.7014878, 0.2920151, 0.13381833, 0.74486643,
+ 0.13818067, 0.18079887, 0.57839566, 0.56782985, 0.5733893, 0.8142381, 0.038408525, 0.61868846,
+ 0.048855904, 0.8661853, 0.091889195, 0.42655867, 0.75064015, 0.41258946, 0.0327612, 0.6939966,
+ 0.5684132, 0.230771, 0.87241197, 0.41159534, 0.95303357, 0.5293433, 0.37525147, 0.91937405,
+ 0.46753627, 0.3657011, 0.58334947, 0.62074995, 0.79216284, 0.9344987, 0.32306752, 0.7569309,
+ 0.8670772, 0.49101356, 0.0095974505, 0.31980786, 0.5587957, 0.6286712, 0.8952423, 0.42964563,
+ 0.24610022, 0.46633002, 0.31894207, 0.39979902, 0.99703586, 0.09658354, 0.10385787, 0.092738345,
+ 0.9319688, 0.066221446, 0.567998, 0.47071677, 0.41960314, 0.722223, 0.79183286, 0.60883737,
+ 0.8055474, 0.6590216, 0.10029357, 0.20768817, 0.2308886, 0.41765857, 0.82652557, 0.11435715,
+ 0.5431178, 0.3349583, 0.55948156, 0.2596266, 0.402992, 0.7129533, 0.13520089, 0.939742,
+ 0.33552873, 0.44276634, 0.16549513, 0.48670354, 0.2104012, 0.9754525, 0.9223382, 0.37095273,
+ 0.26184326, 0.4906111, 0.68878114, 0.7259414, 0.3665008, 0.8523507, 0.33732775, 0.14485414,
+ 0.69918066, 0.40076008, 0.5142605, 0.89977413, 0.52837765, 0.6875541, 0.19875702, 0.8284416,
+ 0.6398044, 0.20458493, 0.8566812, 0.66207755, 0.537102, 0.84423125, 0.6897463, 0.2190155,
+ 0.93102056, 0.62825596, 0.13518804, 0.9768368, 0.5567279, 0.30512935, 0.39843616, 0.83009493,
+ 0.7366834, 0.72934085, 0.9458449, 0.7402775, 0.7288774, 0.100584194, 0.7478564, 0.69076705,
+ 0.99763054, 0.41462737, 0.5604459, 0.002231921, 0.19869287, 0.23542677, 0.41136438, 0.6479746,
+ 0.24400933, 0.33705348, 0.8468991, 0.0058162767, 0.11877123, 0.26026058, 0.83385074, 0.417612,
+ 0.80086476, 0.46976563, 0.79492086, 0.73824483, 0.71716267, 0.36049098, 0.58812624, 0.3940513,
+ 0.0023239073, 0.68416554, 0.1630907, 0.7990368, 0.74170923, 0.45847952, 0.0995642, 0.5392202,
+ 0.45672858, 0.16591415, 0.664447, 0.12247461, 0.28378534, 0.6875144, 0.020322617, 0.6955938,
+ 0.21689159, 0.48721343, 0.7328274, 0.21967441, 0.45823023, 0.39261988, 0.7113237, 0.47642282,
+ 0.8954901, 0.52823293, 0.9394127, 0.25911182, 0.30566335, 0.009611528, 0.9736044, 0.63713956,
+ 0.82650113, 0.16639459, 0.99990803, 0.5145273, 0.07233607, 0.6123276, 0.9062654, 0.7855298,
+ 0.23748927, 0.30767888, 0.5490877, 0.9528571, 0.5958136, 0.71137613, 0.13382663, 0.11335034,
+ 0.449443, 0.09932706, 0.52135324, 0.22994924, 0.6276635, 0.36845186, 0.93582106, 0.609704,
+ 0.9728418, 0.68666786, 0.9035467, 0.21347627, 0.51906675, 0.8404524, 0.2335569, 0.44711703,
+ 0.19230975, 0.027307436, 0.29597348, 0.11739075, 0.6876064, 0.5057953, 0.6232577, 0.604564,
+ 0.58094805, 0.94729763, 0.9821851, 0.15055138, 0.8435322, 0.7584666, 0.8806093, 0.18411398,
+ 0.3944063, 0.8260624, 0.8096688, 0.20633629, 0.48825827, 0.74365515, 0.009476059, 0.45804924,
+ 0.23057352, 0.39020398, 0.5416855, 0.3856682, 0.7087808, 0.69278914, 0.26646304, 0.39703688,
+ 0.074121974, 0.10197067, 0.76054734, 0.5685061, 0.41540262, 0.016435882, 0.42574394, 0.94364774,
+ 0.47606933, 0.91678923, 0.6490012, 0.68036586, 0.38626674, 0.78526974, 0.7661718, 0.2143752,
+ 0.80605865, 0.7194327, 0.81907, 0.69300437, 0.030783592, 0.027220597, 0.9588587, 0.4486546,
+ 0.017831376, 0.83792424, 0.8868172, 0.2974024, 0.9641097, 0.23758952, 0.8957832, 0.8881589,
+ 0.6808346, 0.5851483, 0.0764294, 0.74156153, 0.9979193, 0.3121031, 0.7687113, 0.37797043,
+ 0.40031847, 0.86602104, 0.730267, 0.57146907, 0.094653964, 0.32911018, 0.07178252, 0.4453038,
+ 0.62403214, 0.32731032, 0.5796096, 0.9893481, 0.87371916, 0.5734587, 0.3662533, 0.046901383,
+ 0.14311191, 0.31189272, 0.5506748, 0.5774784, 0.12961864, 0.12834151, 0.97953796, 0.23847981,
+ 0.021006035, 0.76084226, 0.99953127, 0.8011185, 0.7088403, 0.024610326, 0.21645589, 0.49395552,
+ 0.9507214, 0.44109955, 0.2926859, 0.16476253, 0.29695365, 0.3873897, 0.35400063, 0.6887212,
+ 0.7661417, 0.44151342, 0.67337024, 0.6367994, 0.65797997, 0.906435, 0.014439769, 0.10737592,
+ 0.21889497, 0.029528014, 0.5984496, 0.6860266, 0.76142836, 0.19123298, 0.24835177, 0.27197698,
+ 0.8864831, 0.49178717, 0.550463, 0.3338117, 0.32957888, 0.27066407, 0.7364635, 0.59942186,
+ 0.11085444, 0.08565405, 0.03862678, 0.4326196, 0.28077278, 0.20149076, 0.7499477, 0.7557222,
+ 0.95789206, 0.86195356, 0.8113367, 0.6881052, 0.45497125, 0.34273857, 0.5804998, 0.11457099,
+ 0.7464025, 0.8921554, 0.5822235, 0.6793123, 0.42616072, 0.5304293, 0.7325272, 0.7594884,
+ 0.19274779, 0.02070892, 0.27827948, 0.8051665, 0.83692664, 0.020188946, 0.35914233, 0.49547768,
+ 0.70504993, 0.07394841, 0.525945, 0.5723259, 0.8678083, 0.5818202, 0.8266031, 0.017404223,
+ 0.27958027, 0.84272736, 0.7281345, 0.8994748, 0.3798963, 0.5602465, 0.8170057, 0.5437445,
+ 0.9112873, 0.43589205, 0.5874092, 0.4374235, 0.68844056, 0.057151183, 0.1732611, 0.58042514,
+ 0.35312688, 0.2791384, 0.23987181, 0.26006386, 0.9232113, 0.94478124, 0.9187956, 0.93770313,
+ 0.50281125, 0.31585902, 0.9830553, 0.38102284, 0.8167936, 0.008173941, 0.24676272, 0.16458233,
+ 0.06555225, 0.5648193, 0.39973202, 0.58343333, 0.8022948, 0.8330524, 0.3795921, 0.63250124,
+ 0.20370321, 0.734535, 0.8938792, 0.40103462, 0.43277976, 0.92171884, 0.8070371, 0.64789873,
+ 0.9006873, 0.94551986, 0.21919903, 0.5886699, 0.34194836, 0.5665393, 0.09419294, 0.33479902,
+ 0.92393184, 0.7904314, 0.39666355, 0.0640373, 0.5771913, 0.43598288, 0.7269509, 0.90311337,
+ 0.18912931, 0.42282686, 0.37187123, 0.12362129, 0.65741915, 0.5898278, 0.77813035, 0.5200745,
+ 0.8995463, 0.6073706, 0.056360655, 0.18867631, 0.05090209, 0.51776093, 0.5049234, 0.5810924,
+ 0.5088219, 0.3351565, 0.48033553, 0.87127376, 0.7889749, 0.65809286, 0.822634, 0.49901298,
+ 0.47062632, 0.064933024, 0.65950155, 0.0118634105, 0.43638885, 0.3155548, 0.055309944, 0.76772034,
+ 0.007584079, 0.9907658, 0.2119053, 0.0099529, 0.5498476, 0.68341583, 0.9904796, 0.31085956,
+ 0.16738948, 0.6991246, 0.6891236, 0.7345778, 0.5101786, 0.9055166, 0.28389692, 0.40617087,
+ 0.285508, 0.8155711, 0.5552154, 0.24203478, 0.95564735, 0.8556771, 0.11413846, 0.53103644,
+ 0.6001929, 0.8728583, 0.652995, 0.59248614, 0.9303262, 0.76626694, 0.083685614, 0.5839915,
+ 0.55206066, 0.28864032, 0.18109223, 0.06013629, 0.30585563, 0.49497047, 0.031244803, 0.8254061,
+ 0.34467688, 0.16947599, 0.70388424, 0.089850344, 0.9689693, 0.088056214, 0.9888344, 0.56510967,
+ 0.7810361, 0.25333068, 0.72635543, 0.6208177, 0.7603394, 0.81327516, 0.812073, 0.15190694,
+ 0.8766273, 0.68086886, 0.40976003, 0.6769893, 0.03042084, 0.39799348, 0.38053334, 0.40112254,
+ 0.61543894, 0.10513203, 0.18251711, 0.22153829, 0.7244244, 0.22376063, 0.10031522, 0.79053754,
+ 0.7843263, 0.7298093, 0.8973579, 0.7861713, 0.15179288, 0.024288114, 0.56206715, 0.51213664,
+ 0.8840239, 0.08788527, 0.81145, 0.6769955, 0.039911535, 0.4628679, 0.82365215, 0.7387855,
+ 0.47656733, 0.029185295, 0.18350895, 0.62498677, 0.08521046, 0.35425547, 0.7949853, 0.9466834,
+ 0.78894264, 0.30276173, 0.4744114, 0.86383724, 0.9055391, 0.7672961, 0.8406853, 0.5572755,
+ 0.15301545, 0.9358179, 0.83649135, 0.030530108, 0.9159173, 0.025901658, 0.00011405395, 0.8523392,
+ 0.1188017, 0.89762336, 0.7929654, 0.9425356, 0.58654344, 0.7035378, 0.361211, 0.15257105,
+ 0.2814799, 0.44373164, 0.744971, 0.6952391, 0.040251687, 0.47532842, 0.70532703, 0.43007088,
+ 0.93482405, 0.9506745, 0.9972287, 0.84903115, 0.5498767, 0.6982299, 0.60659754, 0.116727814,
+ 0.24719998, 0.25417453, 0.5239801, 0.10409364, 0.6263765, 0.79312205, 0.82286817, 0.45066565,
+ 0.02907124, 0.33116972, 0.5061851, 0.1875871, 0.56129, 0.8524497, 0.36013994, 0.085404865,
+ 0.94155073, 0.32184035, 0.58235735, 0.46180746, 0.022325099, 0.14544618, 0.5170238, 0.67768705,
+ 0.23049083, 0.4064205, 0.09570609, 0.9652428, 0.028672969, 0.1510829, 0.30246252, 0.4205718,
+ 0.2910258, 0.67623764, 0.69533557, 0.33236894, 0.17955771, 0.25711736, 0.5261945, 0.48835787};
float rndf() {
- static int _cur_rnd = 0;
- if (_cur_rnd > _rnd_count)
- _cur_rnd = 0;
- return _rnd[_cur_rnd++];
+ static int _cur_rnd = 0;
+ if (_cur_rnd > _rnd_count)
+ _cur_rnd = 0;
+ return _rnd[_cur_rnd++];
}
#include <string.h>
#if defined(_WIN32) || defined(_WIN64)
-int gettimeofday(struct timeval * tp, void * tzp)
-{
- // FILETIME Jan 1 1970 00:00:00
- // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
- static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);
-
- SYSTEMTIME nSystemTime;
- FILETIME nFileTime;
- uint64_t nTime;
-
- GetSystemTime( &nSystemTime );
- SystemTimeToFileTime( &nSystemTime, &nFileTime );
- nTime = ((uint64_t)nFileTime.dwLowDateTime ) ;
- nTime += ((uint64_t)nFileTime.dwHighDateTime) << 32;
-
- tp->tv_sec = (long) ((nTime - EPOCH) / 10000000L);
- tp->tv_usec = (long) (nSystemTime.wMilliseconds * 1000);
- return 0;
+int gettimeofday(struct timeval *tp, void *tzp) {
+ // FILETIME Jan 1 1970 00:00:00
+ // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
+ static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
+
+ SYSTEMTIME nSystemTime;
+ FILETIME nFileTime;
+ uint64_t nTime;
+
+ GetSystemTime(&nSystemTime);
+ SystemTimeToFileTime(&nSystemTime, &nFileTime);
+ nTime = ((uint64_t)nFileTime.dwLowDateTime);
+ nTime += ((uint64_t)nFileTime.dwHighDateTime) << 32;
+
+ tp->tv_sec = (long)((nTime - EPOCH) / 10000000L);
+ tp->tv_usec = (long)(nSystemTime.wMilliseconds * 1000);
+ return 0;
}
#endif
-float panX = 0.f;
-float panY = 0.f;
-float lastX = 0.f;
-float lastY = 0.f;
-float zoom = 1.0f;
-bool mouseDown = false;
-
-VkvgDevice device = NULL;
-VkvgSurface surf = NULL;
-
-uint32_t test_size = 500; // items drawn in one run, or complexity
-uint32_t iterations = 500; // repeat test n times
-uint32_t test_width = 512;
-uint32_t test_height= 512;
-bool test_vsync = false;
-bool quiet = false;//if true, don't print details and head row
-bool first_test = true; //if multiple tests, dont print header row.
-bool no_test_size= false;//several test consist of a single draw sequence without looping 'size' times
- //those test must be preceded by setting no_test_size to 'true'
-int test_index = 0;
-int single_test = -1; //if not < 0, contains the index of the single test to run
-
-
-static bool paused = false;
-static bool offscreen = false;
-static bool threadAware = false;
-static VkSampleCountFlags samples = VK_SAMPLE_COUNT_1_BIT;
+float panX = 0.f;
+float panY = 0.f;
+float lastX = 0.f;
+float lastY = 0.f;
+float zoom = 1.0f;
+bool mouseDown = false;
+
+VkvgDevice device = NULL;
+VkvgSurface surf = NULL;
+
+uint32_t test_size = 500; // items drawn in one run, or complexity
+uint32_t iterations = 500; // repeat test n times
+uint32_t test_width = 512;
+uint32_t test_height = 512;
+bool test_vsync = false;
+bool quiet = false; // if true, don't print details and head row
+bool first_test = true; // if multiple tests, dont print header row.
+bool no_test_size = false; // several test consist of a single draw sequence without looping 'size' times
+ // those test must be preceded by setting no_test_size to 'true'
+int test_index = 0;
+int single_test = -1; // if not < 0, contains the index of the single test to run
+
+static bool paused = false;
+static bool offscreen = false;
+static bool threadAware = false;
+static VkSampleCountFlags samples = VK_SAMPLE_COUNT_1_BIT;
static VkPhysicalDeviceType preferedPhysicalDeviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
-static vk_engine_t* e;
-static char* saveToPng = NULL;
-
-static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
- if (action != GLFW_PRESS)
- return;
- switch (key) {
- case GLFW_KEY_SPACE:
- paused = !paused;
- break;
- case GLFW_KEY_ESCAPE :
- glfwSetWindowShouldClose(window, GLFW_TRUE);
- break;
+static vk_engine_t *e;
+static char *saveToPng = NULL;
+
+static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+ if (action != GLFW_PRESS)
+ return;
+ switch (key) {
+ case GLFW_KEY_SPACE:
+ paused = !paused;
+ break;
+ case GLFW_KEY_ESCAPE:
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+ break;
#ifdef VKVG_WIRED_DEBUG
- case GLFW_KEY_F1:
- vkvg_wired_debug ^= (1U << 0);
- break;
- case GLFW_KEY_F2:
- vkvg_wired_debug ^= (1U << 1);
- break;
- case GLFW_KEY_F3:
- vkvg_wired_debug ^= (1U << 2);
- break;
+ case GLFW_KEY_F1:
+ vkvg_wired_debug ^= (1U << 0);
+ break;
+ case GLFW_KEY_F2:
+ vkvg_wired_debug ^= (1U << 1);
+ break;
+ case GLFW_KEY_F3:
+ vkvg_wired_debug ^= (1U << 2);
+ break;
#endif
- }
+ }
}
-static void char_callback (GLFWwindow* window, uint32_t c){}
-static void mouse_move_callback(GLFWwindow* window, double x, double y){
- if (mouseDown) {
- panX += ((float)x-lastX);
- panY += ((float)y-lastY);
- }
- lastX = (float)x;
- lastY = (float)y;
+static void char_callback(GLFWwindow *window, uint32_t c) {}
+static void mouse_move_callback(GLFWwindow *window, double x, double y) {
+ if (mouseDown) {
+ panX += ((float)x - lastX);
+ panY += ((float)y - lastY);
+ }
+ lastX = (float)x;
+ lastY = (float)y;
}
-static void scroll_callback(GLFWwindow* window, double x, double y){
- if (y<0.f)
- zoom *= 0.5f;
- else
- zoom *= 2.0f;
+static void scroll_callback(GLFWwindow *window, double x, double y) {
+ if (y < 0.f)
+ zoom *= 0.5f;
+ else
+ zoom *= 2.0f;
}
-static void mouse_button_callback(GLFWwindow* window, int but, int state, int modif){
- if (but != GLFW_MOUSE_BUTTON_1)
- return;
- if (state == GLFW_TRUE)
- mouseDown = true;
- else
- mouseDown = false;
+static void mouse_button_callback(GLFWwindow *window, int but, int state, int modif) {
+ if (but != GLFW_MOUSE_BUTTON_1)
+ return;
+ if (state == GLFW_TRUE)
+ mouseDown = true;
+ else
+ mouseDown = false;
}
-double time_diff(struct timeval x , struct timeval y)
-{
- double x_ms , y_ms , diff;
+double time_diff(struct timeval x, struct timeval y) {
+ double x_ms, y_ms, diff;
- x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
- y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
+ x_ms = (double)x.tv_sec * 1000000 + (double)x.tv_usec;
+ y_ms = (double)y.tv_sec * 1000000 + (double)y.tv_usec;
- diff = (double)y_ms - (double)x_ms;
+ diff = (double)y_ms - (double)x_ms;
- return diff;
+ return diff;
}
/* from caskbench */
-double get_tick (void)
-{
- struct timeval now;
- gettimeofday (&now, NULL);
- return (double)now.tv_sec + (double)now.tv_usec / 1000000.0;
+double get_tick(void) {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ return (double)now.tv_sec + (double)now.tv_usec / 1000000.0;
}
-double median_run_time (double data[], int n)
-{
- double temp;
- int i, j;
- for (i = 0; i < n; i++)
- for (j = i+1; j < n; j++)
- {
- if (data[i] > data[j])
- {
- temp = data[j];
- data[j] = data[i];
- data[i] = temp;
- }
- }
- if (n % 2 == 0)
- return (data[n/2] + data[n/2-1])/2;
- return data[n/2];
+double median_run_time(double data[], int n) {
+ double temp;
+ int i, j;
+ for (i = 0; i < n; i++)
+ for (j = i + 1; j < n; j++) {
+ if (data[i] > data[j]) {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ if (n % 2 == 0)
+ return (data[n / 2] + data[n / 2 - 1]) / 2;
+ return data[n / 2];
}
-double standard_deviation (const double data[], int n, double mean)
-{
- double sum_deviation = 0.0;
- int i;
- for (i = 0; i < n; ++i)
- sum_deviation += (data[i]-mean) * (data[i]-mean);
- return sqrt (sum_deviation / n);
+double standard_deviation(const double data[], int n, double mean) {
+ double sum_deviation = 0.0;
+ int i;
+ for (i = 0; i < n; ++i)
+ sum_deviation += (data[i] - mean) * (data[i] - mean);
+ return sqrt(sum_deviation / n);
}
/***************/
-void init_test (uint32_t width, uint32_t height){
- if (test_vsync)
- e = vkengine_create (preferedPhysicalDeviceType, VK_PRESENT_MODE_FIFO_KHR, width, height);
- else
- e = vkengine_create (preferedPhysicalDeviceType, VK_PRESENT_MODE_MAILBOX_KHR, width, height);
+void init_test(uint32_t width, uint32_t height) {
+ if (test_vsync)
+ e = vkengine_create(preferedPhysicalDeviceType, VK_PRESENT_MODE_FIFO_KHR, width, height);
+ else
+ e = vkengine_create(preferedPhysicalDeviceType, VK_PRESENT_MODE_MAILBOX_KHR, width, height);
- VkhPresenter r = e->renderer;
- vkengine_set_key_callback (e, key_callback);
- vkengine_set_mouse_but_callback(e, mouse_button_callback);
- vkengine_set_cursor_pos_callback(e, mouse_move_callback);
- vkengine_set_scroll_callback(e, scroll_callback);
+ VkhPresenter r = e->renderer;
+ vkengine_set_key_callback(e, key_callback);
+ vkengine_set_mouse_but_callback(e, mouse_button_callback);
+ vkengine_set_cursor_pos_callback(e, mouse_move_callback);
+ vkengine_set_scroll_callback(e, scroll_callback);
- vkvg_device_create_info_t info = {
- samples,
- false,
- vkh_app_get_inst(e->app),
- r->dev->phy,
- r->dev->dev,
- r->qFam,
- 0
- };
+ vkvg_device_create_info_t info = {samples, false, vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0};
device = vkvg_device_create(&info);
- surf = vkvg_surface_create(device, width, height);
+ surf = vkvg_surface_create(device, width, height);
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), width, height);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), width, height);
}
-void clear_test () {
- vkDeviceWaitIdle(e->dev->dev);
+void clear_test() {
+ vkDeviceWaitIdle(e->dev->dev);
- vkvg_surface_destroy (surf);
- vkvg_device_destroy (device);
+ vkvg_surface_destroy(surf);
+ vkvg_device_destroy(device);
- vkengine_destroy (e);
+ vkengine_destroy(e);
}
#ifdef VKVG_TEST_DIRECT_DRAW
-VkvgSurface* surfaces;
+VkvgSurface *surfaces;
#endif
-void _print_usage_and_exit () {
- printf("\nUsage: test [options]\n\n");
- printf("\t-i iterations:\tSpecify the repeat count for the test.\n");
- printf("\t-s size:\tWhen applicable, specify the size of the test.\n");
- printf("\t-x width:\tOutput surface width.\n");
- printf("\t-y height:\tOutput surface height.\n");
- printf("\t-S num samples:\tOutput surface filter, default is 1.\n");
+void _print_usage_and_exit() {
+ printf("\nUsage: test [options]\n\n");
+ printf("\t-i iterations:\tSpecify the repeat count for the test.\n");
+ printf("\t-s size:\tWhen applicable, specify the size of the test.\n");
+ printf("\t-x width:\tOutput surface width.\n");
+ printf("\t-y height:\tOutput surface height.\n");
+ printf("\t-S num samples:\tOutput surface filter, default is 1.\n");
printf("\t-g gpu_type:\tSet prefered GPU type:\n");
- printf("\t\t\t - 0: Other\n");
- printf("\t\t\t - 1: Integrated (second choice)\n");
- printf("\t\t\t - 2: Discrete (first choice)\n");
- printf("\t\t\t - 3: Virtual\n");
- printf("\t\t\t - 4: Cpu\n");
- printf("\t-l line_width:\tset lines width for stokes.\n");
- printf("\t-j line_join:\tset line joins for strokes:\n");
- printf("\t\t\t - m: Mitter(default)\n");
- printf("\t\t\t - r: Rount\n");
- printf("\t\t\t - b: Bevel\n");
- printf("\t-c line_cap:\tset line caps for strokes:\n");
- printf("\t\t\t - b: Butt (default)\n");
- printf("\t\t\t - r: Rount\n");
- printf("\t\t\t - s: Square\n");
- printf("\t-f fill_rule:\tset current fill rule:\n");
- printf("\t\t\t - 0: Even Odd\n");
- printf("\t\t\t - 1: Non Zero\n");
- printf("\t-d:\t\tenable dashes.\n");
- printf("\t-n index:\tRun only a single test, zero based index.\n");
- printf("\t-q:\t\tQuiet, don't print measures table head row, usefull for batch tests.\n");
- printf("\t-t:\t\tThread aware, set device in multithreading aware mode.\n");
- printf("\t-p:\t\tPrint test details and exit without performing test, usefull to print details in logs.\n");
- printf("\t-vsync:\t\tEnable VSync, disabled by default.\n");
- printf("\t-o:\t\tPerform test offscreen.\n");
- printf("\t-w filepath:\twrite last image to png.\n");
+ printf("\t\t\t - 0: Other\n");
+ printf("\t\t\t - 1: Integrated (second choice)\n");
+ printf("\t\t\t - 2: Discrete (first choice)\n");
+ printf("\t\t\t - 3: Virtual\n");
+ printf("\t\t\t - 4: Cpu\n");
+ printf("\t-l line_width:\tset lines width for stokes.\n");
+ printf("\t-j line_join:\tset line joins for strokes:\n");
+ printf("\t\t\t - m: Mitter(default)\n");
+ printf("\t\t\t - r: Rount\n");
+ printf("\t\t\t - b: Bevel\n");
+ printf("\t-c line_cap:\tset line caps for strokes:\n");
+ printf("\t\t\t - b: Butt (default)\n");
+ printf("\t\t\t - r: Rount\n");
+ printf("\t\t\t - s: Square\n");
+ printf("\t-f fill_rule:\tset current fill rule:\n");
+ printf("\t\t\t - 0: Even Odd\n");
+ printf("\t\t\t - 1: Non Zero\n");
+ printf("\t-d:\t\tenable dashes.\n");
+ printf("\t-n index:\tRun only a single test, zero based index.\n");
+ printf("\t-q:\t\tQuiet, don't print measures table head row, usefull for batch tests.\n");
+ printf("\t-t:\t\tThread aware, set device in multithreading aware mode.\n");
+ printf("\t-p:\t\tPrint test details and exit without performing test, usefull to print details in logs.\n");
+ printf("\t-vsync:\t\tEnable VSync, disabled by default.\n");
+ printf("\t-o:\t\tPerform test offscreen.\n");
+ printf("\t-w filepath:\twrite last image to png.\n");
#ifdef DEBUG
- printf("\t-L level:\tLog level in hexadecimal format (0xFF), 0 to disable.\n");
- printf("\t\t\tsee vkvg.h for possible values.\n");
+ printf("\t-L level:\tLog level in hexadecimal format (0xFF), 0 to disable.\n");
+ printf("\t\t\tsee vkvg.h for possible values.\n");
#endif
- printf("\t-h:\t\tThis help message.\n");
- printf("\n");
- exit(-1);
+ printf("\t-h:\t\tThis help message.\n");
+ printf("\n");
+ exit(-1);
}
-void _parse_args (int argc, char* argv[]) {
- bool printTestDetailsAndExit = false;
- for (int i = 1; i < argc; i++) {
- if (strcmp (argv[i], "-h\0") == 0)
- _print_usage_and_exit ();
- if (strcmp (argv[i], "-p\0") == 0)
- printTestDetailsAndExit = true;
- else if (strcmp (argv[i], "-vsync\0") == 0)
- test_vsync = true;
- else if (strcmp(argv[i], "-q\0") == 0)
- quiet = true;
- else if (strcmp(argv[i], "-t\0") == 0)
- threadAware = true;
- else if (strcmp (argv[i], "-i\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- iterations = atoi (argv[i]);
- }else if (strcmp (argv[i], "-x\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- test_width = atoi (argv[i]);
- }else if (strcmp (argv[i], "-y\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- test_height = atoi (argv[i]);
- }else if (strcmp (argv[i], "-n\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- single_test = atoi (argv[i]);
- }else if (strcmp (argv[i], "-s\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- test_size = atoi (argv[i]);
- }else if (strcmp (argv[i], "-S\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- samples = (VkSampleCountFlags)atoi (argv[i]);
- }else if (strcmp (argv[i], "-g\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- preferedPhysicalDeviceType = (VkPhysicalDeviceType)atoi (argv[i]);
- }else if (strcmp (argv[i], "-l\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- line_width = atoi (argv[i]);
- }else if (strcmp (argv[i], "-d\0") == 0) {
- dashes_count = 2;
- }else if (strcmp (argv[i], "-f\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- fill_rule = atoi (argv[i]);
- } else if (strcmp (argv[i], "-o\0") == 0) {
- offscreen = true;
- }else if (strcmp (argv[i], "-j\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- switch (argv[i][0]) {
- case 'm':
- line_join = VKVG_LINE_JOIN_MITER;
- break;
- case 'r':
- line_join = VKVG_LINE_JOIN_ROUND;
- break;
- case 'b':
- line_join = VKVG_LINE_JOIN_BEVEL;
- break;
- default:
- _print_usage_and_exit();
- }
- }else if (strcmp (argv[i], "-c\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- switch (argv[i][0]) {
- case 'b':
- line_cap = VKVG_LINE_CAP_BUTT;
- break;
- case 'r':
- line_cap = VKVG_LINE_CAP_ROUND;
- break;
- case 's':
- line_cap = VKVG_LINE_CAP_SQUARE;
- break;
- default:
- _print_usage_and_exit();
- }
- }else if (strcmp (argv[i], "-w\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- saveToPng = argv[i];
+void _parse_args(int argc, char *argv[]) {
+ bool printTestDetailsAndExit = false;
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-h\0") == 0)
+ _print_usage_and_exit();
+ if (strcmp(argv[i], "-p\0") == 0)
+ printTestDetailsAndExit = true;
+ else if (strcmp(argv[i], "-vsync\0") == 0)
+ test_vsync = true;
+ else if (strcmp(argv[i], "-q\0") == 0)
+ quiet = true;
+ else if (strcmp(argv[i], "-t\0") == 0)
+ threadAware = true;
+ else if (strcmp(argv[i], "-i\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ iterations = atoi(argv[i]);
+ } else if (strcmp(argv[i], "-x\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ test_width = atoi(argv[i]);
+ } else if (strcmp(argv[i], "-y\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ test_height = atoi(argv[i]);
+ } else if (strcmp(argv[i], "-n\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ single_test = atoi(argv[i]);
+ } else if (strcmp(argv[i], "-s\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ test_size = atoi(argv[i]);
+ } else if (strcmp(argv[i], "-S\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ samples = (VkSampleCountFlags)atoi(argv[i]);
+ } else if (strcmp(argv[i], "-g\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ preferedPhysicalDeviceType = (VkPhysicalDeviceType)atoi(argv[i]);
+ } else if (strcmp(argv[i], "-l\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ line_width = atoi(argv[i]);
+ } else if (strcmp(argv[i], "-d\0") == 0) {
+ dashes_count = 2;
+ } else if (strcmp(argv[i], "-f\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ fill_rule = atoi(argv[i]);
+ } else if (strcmp(argv[i], "-o\0") == 0) {
+ offscreen = true;
+ } else if (strcmp(argv[i], "-j\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ switch (argv[i][0]) {
+ case 'm':
+ line_join = VKVG_LINE_JOIN_MITER;
+ break;
+ case 'r':
+ line_join = VKVG_LINE_JOIN_ROUND;
+ break;
+ case 'b':
+ line_join = VKVG_LINE_JOIN_BEVEL;
+ break;
+ default:
+ _print_usage_and_exit();
+ }
+ } else if (strcmp(argv[i], "-c\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ switch (argv[i][0]) {
+ case 'b':
+ line_cap = VKVG_LINE_CAP_BUTT;
+ break;
+ case 'r':
+ line_cap = VKVG_LINE_CAP_ROUND;
+ break;
+ case 's':
+ line_cap = VKVG_LINE_CAP_SQUARE;
+ break;
+ default:
+ _print_usage_and_exit();
+ }
+ } else if (strcmp(argv[i], "-w\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ saveToPng = argv[i];
#ifdef DEBUG
- }else if (strcmp (argv[i], "-L\0") == 0) {
- if (argc -1 < ++i)
- _print_usage_and_exit();
- sscanf(argv[i], "%x", &vkvg_log_level);
+ } else if (strcmp(argv[i], "-L\0") == 0) {
+ if (argc - 1 < ++i)
+ _print_usage_and_exit();
+ sscanf(argv[i], "%x", &vkvg_log_level);
#endif
- }else
- _print_usage_and_exit();
- }
- if (printTestDetailsAndExit) {
+ } else
+ _print_usage_and_exit();
+ }
+ if (printTestDetailsAndExit) {
#ifdef DEBUG
- printf("Debug build\n");
+ printf("Debug build\n");
#else
- printf("Release build\n");
+ printf("Release build\n");
#endif
#ifdef VKVG_USE_RENDERDOC
- printf("Render doc enabled\n");
+ printf("Render doc enabled\n");
#endif
#ifdef VKVG_USE_VALIDATION
- printf("Validation:\tenabled\n");
+ printf("Validation:\tenabled\n");
#else
- printf("Validation:\no\n");
+ printf("Validation:\no\n");
#endif
- printf("surf dims:\t%d x %d\n", test_width, test_height);
- printf("Samples:\t%d\n", samples);
- printf("Gpu type:\t");
- switch (preferedPhysicalDeviceType) {
- case VK_PHYSICAL_DEVICE_TYPE_OTHER:
- printf("Other\n");
- break;
- case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
- printf("Integrated\n");
- break;
- case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
- printf("Discrete\n");
- break;
- case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
- printf("Virtual\n");
- break;
- case VK_PHYSICAL_DEVICE_TYPE_CPU:
- printf("CPU\n");
- break;
- }
-
- if (offscreen)
- printf("Offscreen:\ttrue\n");
- else
- printf("Offscreen:\tfalse\n");
-
- if (fill_rule == VKVG_FILL_RULE_EVEN_ODD)
- printf("Fillrule:\tEven/Odd\n");
- else
- printf("Fillrule:\tNon zero\n");
-
- printf("\n");
- exit(0);
- }
+ printf("surf dims:\t%d x %d\n", test_width, test_height);
+ printf("Samples:\t%d\n", samples);
+ printf("Gpu type:\t");
+ switch (preferedPhysicalDeviceType) {
+ case VK_PHYSICAL_DEVICE_TYPE_OTHER:
+ printf("Other\n");
+ break;
+ case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
+ printf("Integrated\n");
+ break;
+ case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
+ printf("Discrete\n");
+ break;
+ case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
+ printf("Virtual\n");
+ break;
+ case VK_PHYSICAL_DEVICE_TYPE_CPU:
+ printf("CPU\n");
+ break;
+ }
+
+ if (offscreen)
+ printf("Offscreen:\ttrue\n");
+ else
+ printf("Offscreen:\tfalse\n");
+
+ if (fill_rule == VKVG_FILL_RULE_EVEN_ODD)
+ printf("Fillrule:\tEven/Odd\n");
+ else
+ printf("Fillrule:\tNon zero\n");
+
+ printf("\n");
+ exit(0);
+ }
}
-void _print_results (const char *testName, int argc, char* argv[], uint32_t i, double run_total, double* run_time_values) {
- char* whoami;
- (whoami = strrchr(argv[0], '/')) ? ++whoami : (whoami = argv[0]);
+void _print_results(const char *testName, int argc, char *argv[], uint32_t i, double run_total,
+ double *run_time_values) {
+ char *whoami;
+ (whoami = strrchr(argv[0], '/')) ? ++whoami : (whoami = argv[0]);
- double avg_run_time = run_total / (double)i;
- double med_run_time = median_run_time (run_time_values, i);
- double standard_dev = standard_deviation (run_time_values, i, avg_run_time);
- double avg_frames_per_second = (1.0 / avg_run_time);
- avg_frames_per_second = (avg_frames_per_second<9999) ? avg_frames_per_second:9999;
+ double avg_run_time = run_total / (double)i;
+ double med_run_time = median_run_time(run_time_values, i);
+ double standard_dev = standard_deviation(run_time_values, i, avg_run_time);
+ double avg_frames_per_second = (1.0 / avg_run_time);
+ avg_frames_per_second = (avg_frames_per_second < 9999) ? avg_frames_per_second : 9999;
- if (!quiet && (test_index == 0 || test_index == single_test)) {
+ if (!quiet && (test_index == 0 || test_index == single_test)) {
#if VKVG_DBG_STATS
- printf ("_____________________________________________________________________________________________________________________________\n");
- printf ("| N° | Test File Name | Sub Test | Iter | Size | Pts |Pathes| Vx cache | Ix cache | VBO | IBO |\n");
- printf ("|----|-----------------|---------------------------|------|------|-------|------|----------|----------|----------|----------|\n");
+ printf("_______________________________________________________________________________________________________"
+ "______________________\n");
+ printf("| N° | Test File Name | Sub Test | Iter | Size | Pts |Pathes| Vx cache | Ix cache "
+ "| VBO | IBO |\n");
+ printf("|----|-----------------|---------------------------|------|------|-------|------|----------|----------|"
+ "----------|----------|\n");
#else
- printf ("__________________________________________________________________________________________________________\n");
- printf ("| N° | Test File Name | Sub Test | Iter | Size | FPS | Average | Median | Sigma |\n");
- printf ("|----|-----------------|---------------------------|------|------|---------|---------|---------|---------|\n");
+ printf("_______________________________________________________________________________________________________"
+ "___\n");
+ printf("| N° | Test File Name | Sub Test | Iter | Size | FPS | Average | Median | Sigma "
+ " |\n");
+ printf("|----|-----------------|---------------------------|------|------|---------|---------|---------|-------"
+ "--|\n");
#endif
- }
-
- printf ("| %2d | %-15s | %-25s | %4d | ", test_index, whoami, testName, i);
- if (no_test_size)
- printf ("%4d | ", 1);
- else
- printf ("%4d | ", test_size);
+ }
+
+ printf("| %2d | %-15s | %-25s | %4d | ", test_index, whoami, testName, i);
+ if (no_test_size)
+ printf("%4d | ", 1);
+ else
+ printf("%4d | ", test_size);
#if VKVG_DBG_STATS
- vkvg_debug_stats_t dbgStats = vkvg_device_get_stats (device);
- printf ("%5d | %4d | %8d | %8d | %8d | %8d |\n",
- dbgStats.sizePoints, dbgStats.sizePathes, dbgStats.sizeVertices,
- dbgStats.sizeIndices, dbgStats.sizeVBO, dbgStats.sizeIBO);
-#else
- printf ("%7.2f | %6.5f | %6.5f | %6.5f |\n",
- avg_frames_per_second, avg_run_time, med_run_time, standard_dev);
-#endif
+ vkvg_debug_stats_t dbgStats = vkvg_device_get_stats(device);
+ printf("%5d | %4d | %8d | %8d | %8d | %8d |\n", dbgStats.sizePoints, dbgStats.sizePathes, dbgStats.sizeVertices,
+ dbgStats.sizeIndices, dbgStats.sizeVBO, dbgStats.sizeIBO);
+#else
+ printf("%7.2f | %6.5f | %6.5f | %6.5f |\n", avg_frames_per_second, avg_run_time, med_run_time, standard_dev);
+#endif
}
#if VKVG_DBG_STATS
-void _print_debug_stats () {
+void _print_debug_stats() {
- vkvg_debug_stats_t dbgStats = vkvg_device_get_stats (device);
- printf ("| %8d | %8d | %8d | %8d | %8d | %8d |\n", dbgStats.sizePoints, dbgStats.sizePathes, dbgStats.sizeVertices,
- dbgStats.sizeIndices, dbgStats.sizeVBO, dbgStats.sizeIBO);
+ vkvg_debug_stats_t dbgStats = vkvg_device_get_stats(device);
+ printf("| %8d | %8d | %8d | %8d | %8d | %8d |\n", dbgStats.sizePoints, dbgStats.sizePathes, dbgStats.sizeVertices,
+ dbgStats.sizeIndices, dbgStats.sizeVBO, dbgStats.sizeIBO);
}
#endif
-void perform_test (void(*testfunc)(void), const char *testName, int argc, char* argv[]) {
- setlocale(LC_ALL, "");
- //dumpLayerExts();
- _parse_args (argc, argv);
+void perform_test(void (*testfunc)(void), const char *testName, int argc, char *argv[]) {
+ setlocale(LC_ALL, "");
+ // dumpLayerExts();
+ _parse_args(argc, argv);
- //init random gen
- struct timeval currentTime;
- gettimeofday(¤tTime, NULL);
- srand((unsigned)currentTime.tv_usec);
+ // init random gen
+ struct timeval currentTime;
+ gettimeofday(¤tTime, NULL);
+ srand((unsigned)currentTime.tv_usec);
- if (iterations == 0)
- iterations = 9999;
+ if (iterations == 0)
+ iterations = 9999;
- if (single_test >= 0 && test_index != single_test) {
- test_index++;
- return;
- }
+ if (single_test >= 0 && test_index != single_test) {
+ test_index++;
+ return;
+ }
- if (offscreen)
- perform_test_offscreen(testfunc, testName, argc, argv);
- else
- perform_test_onscreen(testfunc, testName, argc, argv);
+ if (offscreen)
+ perform_test_offscreen(testfunc, testName, argc, argv);
+ else
+ perform_test_onscreen(testfunc, testName, argc, argv);
}
-void perform_test_offscreen (void(*testfunc)(void), const char *testName, int argc, char* argv[]) {
- uint32_t enabledExtsCount = 0, phyCount = 0;
- const char* enabledExts [10];
+void perform_test_offscreen(void (*testfunc)(void), const char *testName, int argc, char *argv[]) {
+ uint32_t enabledExtsCount = 0, phyCount = 0;
+ const char *enabledExts[10];
#ifdef VKVG_USE_RENDERDOC
- const uint32_t enabledLayersCount = 2;
- const char* enabledLayers[] = {"VK_LAYER_KHRONOS_validation", "VK_LAYER_RENDERDOC_Capture"};
-#elif defined (VKVG_USE_VALIDATION)
- const uint32_t enabledLayersCount = 1;
- const char* enabledLayers[] = {"VK_LAYER_KHRONOS_validation"};
+ const uint32_t enabledLayersCount = 2;
+ const char *enabledLayers[] = {"VK_LAYER_KHRONOS_validation", "VK_LAYER_RENDERDOC_Capture"};
+#elif defined(VKVG_USE_VALIDATION)
+ const uint32_t enabledLayersCount = 1;
+ const char *enabledLayers[] = {"VK_LAYER_KHRONOS_validation"};
#else
- const uint32_t enabledLayersCount = 0;
- const char* enabledLayers[] = {NULL};
+ const uint32_t enabledLayersCount = 0;
+ const char *enabledLayers[] = {NULL};
#endif
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- enabledExts[enabledExtsCount] = "VK_EXT_debug_utils";
- enabledExtsCount++;
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ enabledExts[enabledExtsCount] = "VK_EXT_debug_utils";
+ enabledExtsCount++;
#endif
- VkhApp app = vkh_app_create(1, 1, "vkvgTest", enabledLayersCount, enabledLayers, enabledExtsCount, enabledExts);
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_app_enable_debug_messenger(app
- , VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
- | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
- | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
- , VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
- | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
- //| VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
- //| VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
- , NULL);
+ VkhApp app = vkh_app_create(1, 1, "vkvgTest", enabledLayersCount, enabledLayers, enabledExtsCount, enabledExts);
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_app_enable_debug_messenger(
+ app,
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
+ //| VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
+ //| VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
+ ,
+ NULL);
#endif
- bool deferredResolve = false;
- VkhPhyInfo* phys = vkh_app_get_phyinfos (app, &phyCount, VK_NULL_HANDLE);
- VkhPhyInfo pi = 0;
- if (!vkengine_try_get_phyinfo(phys, phyCount, preferedPhysicalDeviceType, &pi))
- if (!vkengine_try_get_phyinfo(phys, phyCount, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, &pi))
- if (!vkengine_try_get_phyinfo(phys, phyCount, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, &pi))
- pi = phys[0];
-
- uint32_t qCount = 0;
- float qPriorities[] = {0.0};
- VkDeviceQueueCreateInfo pQueueInfos[] = { {0},{0},{0} };
- if (vkh_phyinfo_create_queues (pi, pi->gQueue, 1, qPriorities, &pQueueInfos[qCount]))
- qCount++;
- VkPhysicalDeviceFeatures enabledFeatures = {
- .fillModeNonSolid = true,
- };
-
- VkDeviceCreateInfo device_info = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- .queueCreateInfoCount = qCount,
- .pQueueCreateInfos = (VkDeviceQueueCreateInfo*)&pQueueInfos,
- .pEnabledFeatures = &enabledFeatures};
-
- VkhDevice dev = vkh_device_create(app, pi, &device_info);
+ bool deferredResolve = false;
+ VkhPhyInfo *phys = vkh_app_get_phyinfos(app, &phyCount, VK_NULL_HANDLE);
+ VkhPhyInfo pi = 0;
+ if (!vkengine_try_get_phyinfo(phys, phyCount, preferedPhysicalDeviceType, &pi))
+ if (!vkengine_try_get_phyinfo(phys, phyCount, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, &pi))
+ if (!vkengine_try_get_phyinfo(phys, phyCount, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, &pi))
+ pi = phys[0];
+
+ uint32_t qCount = 0;
+ float qPriorities[] = {0.0};
+ VkDeviceQueueCreateInfo pQueueInfos[] = {{0}, {0}, {0}};
+ if (vkh_phyinfo_create_queues(pi, pi->gQueue, 1, qPriorities, &pQueueInfos[qCount]))
+ qCount++;
+ VkPhysicalDeviceFeatures enabledFeatures = {
+ .fillModeNonSolid = true,
+ };
+
+ VkDeviceCreateInfo device_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ .queueCreateInfoCount = qCount,
+ .pQueueCreateInfos = (VkDeviceQueueCreateInfo *)&pQueueInfos,
+ .pEnabledFeatures = &enabledFeatures};
+
+ VkhDevice dev = vkh_device_create(app, pi, &device_info);
vkvg_device_create_info_t info = {
- samples,
- deferredResolve,
- vkh_app_get_inst(e->app),
- dev->phy,
- dev->dev,
- pi->gQueue,
- 0
- };
+ samples, deferredResolve, vkh_app_get_inst(e->app), dev->phy, dev->dev, pi->gQueue, 0};
device = vkvg_device_create(&info);
- //vkvg_device_set_dpy(device, 96, 96);
+ // vkvg_device_set_dpy(device, 96, 96);
- vkh_app_free_phyinfos (phyCount, phys);
+ vkh_app_free_phyinfos(phyCount, phys);
- surf = vkvg_surface_create(device, test_width, test_height);
+ surf = vkvg_surface_create(device, test_width, test_height);
- double start_time = 0.0, stop_time = 0.0, run_time = 0.0, run_total = 0.0, min_run_time = -1, max_run_time = 0.0;
- double* run_time_values = (double*)malloc(iterations*sizeof(double));
+ double start_time = 0.0, stop_time = 0.0, run_time = 0.0, run_total = 0.0, min_run_time = -1, max_run_time = 0.0;
+ double *run_time_values = (double *)malloc(iterations * sizeof(double));
- uint32_t i = 0;
- while (i < iterations) {
- start_time = get_tick();
+ uint32_t i = 0;
+ while (i < iterations) {
+ start_time = get_tick();
- testfunc();
+ testfunc();
- if (deferredResolve)
- vkvg_surface_resolve(surf);
+ if (deferredResolve)
+ vkvg_surface_resolve(surf);
- stop_time = get_tick();
- run_time = stop_time - start_time;
- run_time_values[i] = run_time;
+ stop_time = get_tick();
+ run_time = stop_time - start_time;
+ run_time_values[i] = run_time;
- if (min_run_time < 0)
- min_run_time = run_time;
- else
- min_run_time = MIN(run_time, min_run_time);
- max_run_time = MAX(run_time, max_run_time);
- run_total += run_time;
- i++;
- }
+ if (min_run_time < 0)
+ min_run_time = run_time;
+ else
+ min_run_time = MIN(run_time, min_run_time);
+ max_run_time = MAX(run_time, max_run_time);
+ run_total += run_time;
+ i++;
+ }
- _print_results (testName, argc, argv, i, run_total, run_time_values);
+ _print_results(testName, argc, argv, i, run_total, run_time_values);
- free (run_time_values);
+ free(run_time_values);
- vkDeviceWaitIdle(dev->dev);
+ vkDeviceWaitIdle(dev->dev);
- if (saveToPng)
- vkvg_surface_write_to_png (surf, saveToPng);
+ if (saveToPng)
+ vkvg_surface_write_to_png(surf, saveToPng);
- vkvg_surface_destroy (surf);
- vkvg_device_destroy (device);
+ vkvg_surface_destroy(surf);
+ vkvg_device_destroy(device);
- vkh_device_destroy (dev);
- vkh_app_destroy (app);
+ vkh_device_destroy(dev);
+ vkh_app_destroy(app);
- test_index++;
+ test_index++;
}
-void perform_test_onscreen (void(*testfunc)(void), const char *testName, int argc, char* argv[]) {
- if (test_vsync)
- e = vkengine_create (preferedPhysicalDeviceType, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
- else
- e = vkengine_create (preferedPhysicalDeviceType, VK_PRESENT_MODE_MAILBOX_KHR, test_width, test_height);
+void perform_test_onscreen(void (*testfunc)(void), const char *testName, int argc, char *argv[]) {
+ if (test_vsync)
+ e = vkengine_create(preferedPhysicalDeviceType, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
+ else
+ e = vkengine_create(preferedPhysicalDeviceType, VK_PRESENT_MODE_MAILBOX_KHR, test_width, test_height);
- VkhPresenter r = e->renderer;
- vkengine_set_key_callback (e, key_callback);
- vkengine_set_mouse_but_callback (e, mouse_button_callback);
- vkengine_set_cursor_pos_callback (e, mouse_move_callback);
- vkengine_set_scroll_callback (e, scroll_callback);
+ VkhPresenter r = e->renderer;
+ vkengine_set_key_callback(e, key_callback);
+ vkengine_set_mouse_but_callback(e, mouse_button_callback);
+ vkengine_set_cursor_pos_callback(e, mouse_move_callback);
+ vkengine_set_scroll_callback(e, scroll_callback);
- vkvg_device_create_info_t info = {
- samples,
- false,
- vkh_app_get_inst(e->app),
- r->dev->phy,
- r->dev->dev,
- r->qFam,
- 0
- };
- device = vkvg_device_create(&info);
+ vkvg_device_create_info_t info = {samples, false, vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0};
+ device = vkvg_device_create(&info);
- vkvg_device_set_dpy (device, 96, 96);
- if (threadAware)
- vkvg_device_set_thread_aware (device, 1);
+ vkvg_device_set_dpy(device, 96, 96);
+ if (threadAware)
+ vkvg_device_set_thread_aware(device, 1);
#ifdef VKVG_TEST_DIRECT_DRAW
- surfaces = (VkvgSurface*)malloc(r->imgCount * sizeof (VkvgSurface));
- for (uint32_t i=0; i < r->imgCount;i++)
- surfaces[i] = vkvg_surface_create_for_VkhImage (device, r->ScBuffers[i]);
+ surfaces = (VkvgSurface *)malloc(r->imgCount * sizeof(VkvgSurface));
+ for (uint32_t i = 0; i < r->imgCount; i++)
+ surfaces[i] = vkvg_surface_create_for_VkhImage(device, r->ScBuffers[i]);
#else
- surf = vkvg_surface_create (device, test_width, test_height);
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ surf = vkvg_surface_create(device, test_width, test_height);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
#endif
- double start_time = 0.0, stop_time = 0.0, run_time = 0.0, run_total = 0.0, min_run_time = -1, max_run_time = 0.0;
- double* run_time_values = (double*)malloc(iterations*sizeof(double));
+ double start_time = 0.0, stop_time = 0.0, run_time = 0.0, run_total = 0.0, min_run_time = -1, max_run_time = 0.0;
+ double *run_time_values = (double *)malloc(iterations * sizeof(double));
- uint32_t i = 0;
+ uint32_t i = 0;
- vkengine_set_title (e, testName);
+ vkengine_set_title(e, testName);
- while (!vkengine_should_close (e) && i < iterations) {
- glfwPollEvents();
+ while (!vkengine_should_close(e) && i < iterations) {
+ glfwPollEvents();
- start_time = get_tick();
+ start_time = get_tick();
#ifdef VKVG_TEST_DIRECT_DRAW
- if (!vkh_presenter_acquireNextImage(r, NULL, NULL)) {
- for (uint32_t i=0; i < r->imgCount;i++)
- vkvg_surface_destroy (surfaces[i]);
+ if (!vkh_presenter_acquireNextImage(r, NULL, NULL)) {
+ for (uint32_t i = 0; i < r->imgCount; i++)
+ vkvg_surface_destroy(surfaces[i]);
- vkh_presenter_create_swapchain (r);
+ vkh_presenter_create_swapchain(r);
- for (uint32_t i=0; i < r->imgCount;i++)
- surfaces[i] = vkvg_surface_create_for_VkhImage (device, r->ScBuffers[i]);
- }else{
- surf = surfaces[r->currentScBufferIndex];
+ for (uint32_t i = 0; i < r->imgCount; i++)
+ surfaces[i] = vkvg_surface_create_for_VkhImage(device, r->ScBuffers[i]);
+ } else {
+ surf = surfaces[r->currentScBufferIndex];
- testfunc();
+ testfunc();
- if (deferredResolve)
- vkvg_multisample_surface_resolve(surf);
+ if (deferredResolve)
+ vkvg_multisample_surface_resolve(surf);
- VkPresentInfoKHR present = { .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
- .swapchainCount = 1,
- .pSwapchains = &r->swapChain,
- .pImageIndices = &r->currentScBufferIndex };
+ VkPresentInfoKHR present = {.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ .swapchainCount = 1,
+ .pSwapchains = &r->swapChain,
+ .pImageIndices = &r->currentScBufferIndex};
- vkQueuePresentKHR(r->queue, &present);
- }
+ vkQueuePresentKHR(r->queue, &present);
+ }
#else
- if (paused)
- continue;
+ if (paused)
+ continue;
- testfunc();
+ testfunc();
if (info.deferredResolve)
- vkvg_surface_resolve(surf);
- if (!vkh_presenter_draw (r)){
- vkh_presenter_get_size (r, &test_width, &test_height);
- vkvg_surface_destroy (surf);
- surf = vkvg_surface_create(device, test_width, test_height);
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
- vkDeviceWaitIdle(r->dev->dev);
- continue;
- }
+ vkvg_surface_resolve(surf);
+ if (!vkh_presenter_draw(r)) {
+ vkh_presenter_get_size(r, &test_width, &test_height);
+ vkvg_surface_destroy(surf);
+ surf = vkvg_surface_create(device, test_width, test_height);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ vkDeviceWaitIdle(r->dev->dev);
+ continue;
+ }
#endif
- stop_time = get_tick();
- run_time = stop_time - start_time;
- run_time_values[i] = run_time;
+ stop_time = get_tick();
+ run_time = stop_time - start_time;
+ run_time_values[i] = run_time;
- if (min_run_time < 0)
- min_run_time = run_time;
- else
- min_run_time = MIN(run_time, min_run_time);
- max_run_time = MAX(run_time, max_run_time);
- run_total += run_time;
- i++;
- }
+ if (min_run_time < 0)
+ min_run_time = run_time;
+ else
+ min_run_time = MIN(run_time, min_run_time);
+ max_run_time = MAX(run_time, max_run_time);
+ run_total += run_time;
+ i++;
+ }
- if (saveToPng)
- vkvg_surface_write_to_png (surf, saveToPng);
+ if (saveToPng)
+ vkvg_surface_write_to_png(surf, saveToPng);
- _print_results (testName, argc, argv, i, run_total, run_time_values);
+ _print_results(testName, argc, argv, i, run_total, run_time_values);
- free (run_time_values);
+ free(run_time_values);
- vkDeviceWaitIdle(e->dev->dev);
+ vkDeviceWaitIdle(e->dev->dev);
#ifdef VKVG_TEST_DIRECT_DRAW
- for (uint32_t i=0; i<r->imgCount;i++)
- vkvg_surface_destroy (surfaces[i]);
+ for (uint32_t i = 0; i < r->imgCount; i++)
+ vkvg_surface_destroy(surfaces[i]);
- free (surfaces);
+ free(surfaces);
#else
- vkvg_surface_destroy (surf);
+ vkvg_surface_destroy(surf);
#endif
-
- vkvg_device_destroy (device);
- vkengine_destroy (e);
-
- test_index++;
-}
+ vkvg_device_destroy(device);
+ vkengine_destroy(e);
+
+ test_index++;
+}
/* common context init for several tests */
-vkvg_fill_rule_t fill_rule = VKVG_FILL_RULE_NON_ZERO;
-vkvg_line_cap_t line_cap = VKVG_LINE_CAP_BUTT;
-vkvg_line_join_t line_join = VKVG_LINE_JOIN_MITER;
-float dashes[] = {10.0f, 6.0f};
-//float dashes[] = {0.0f, 10.0f};
-uint32_t dashes_count= 0;
-float dash_offset = 0;
-float line_width = 2.f;
+vkvg_fill_rule_t fill_rule = VKVG_FILL_RULE_NON_ZERO;
+vkvg_line_cap_t line_cap = VKVG_LINE_CAP_BUTT;
+vkvg_line_join_t line_join = VKVG_LINE_JOIN_MITER;
+float dashes[] = {10.0f, 6.0f};
+// float dashes[] = {0.0f, 10.0f};
+uint32_t dashes_count = 0;
+float dash_offset = 0;
+float line_width = 2.f;
VkvgContext _initCtx() {
- VkvgContext ctx = vkvg_create(surf);
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_set_line_width (ctx,line_width);
- vkvg_set_line_join (ctx, line_join);
- vkvg_set_line_cap (ctx, line_cap);
- vkvg_set_dash (ctx, dashes, dashes_count, dash_offset);
- vkvg_set_fill_rule (ctx, fill_rule);
+ vkvg_set_line_width(ctx, line_width);
+ vkvg_set_line_join(ctx, line_join);
+ vkvg_set_line_cap(ctx, line_cap);
+ vkvg_set_dash(ctx, dashes, dashes_count, dash_offset);
+ vkvg_set_fill_rule(ctx, fill_rule);
- vkvg_clear (ctx);
- return ctx;
+ vkvg_clear(ctx);
+ return ctx;
}
-
-
-const int star_points[11][2] = {
- { 0, 85 },
- { 75, 75 },
- { 100, 10 },
- { 125, 75 },
- { 200, 85 },
- { 150, 125 },
- { 160, 190 },
- { 100, 150 },
- { 40, 190 },
- { 50, 125 },
- { 0, 85 }
-};
-void randomize_color(VkvgContext ctx) {
- vkvg_set_source_rgba(ctx,
- rndf(),
- rndf(),
- rndf(),
- rndf()
- );
-}
-void draw_random_shape (VkvgContext ctx, shape_t shape, float sizeFact) {
- float w = (float)test_width;
- float h = (float)test_height;
-
- float x, y, z, v, r;
-
- randomize_color (ctx);
-
- switch (shape) {
- case SHAPE_LINE:
- x = rndf() * w;
- y = rndf() * h;
- z = rndf() * w;
- v = rndf() * h;
-
- vkvg_move_to(ctx, x, y);
- vkvg_line_to(ctx, z, v);
- vkvg_stroke(ctx);
- break;
- case SHAPE_RECTANGLE:
- z = truncf((sizeFact*w*rndf())+1.f);
- v = truncf((sizeFact*h*rndf())+1.f);
- x = truncf((w-z)*rndf());
- y = truncf((h-v)*rndf());
-
- vkvg_rectangle(ctx, x+1, y+1, z, v);
- break;
- case SHAPE_ROUNDED_RECTANGLE:
- z = truncf((sizeFact*w*rndf())+1.f);
- v = truncf((sizeFact*h*rndf())+1.f);
- x = truncf((w-z)*rndf());
- y = truncf((h-v)*rndf());
- r = truncf((0.2f*z*rndf())+1.f);
-
- if ((r > v / 2) || (r > z / 2))
- r = MIN(v / 2, z / 2);
-
- vkvg_move_to(ctx, x, y + r);
- vkvg_arc(ctx, x + r, y + r, r, (float)M_PI, (float)-M_PI_2);
- vkvg_line_to(ctx, x + z - r, y);
- vkvg_arc(ctx, x + z - r, y + r, r, (float)-M_PI_2, 0);
- vkvg_line_to(ctx, x + z, y + v - r);
- vkvg_arc(ctx, x + z - r, y + v - r, r, 0, (float)M_PI_2);
- vkvg_line_to(ctx, x + r, y + v);
- vkvg_arc(ctx, x + r, y + v - r, r, (float)M_PI_2, (float)M_PI);
- vkvg_line_to(ctx, x, y + r);
- vkvg_close_path(ctx);
- break;
- case SHAPE_CIRCLE:
- /*x = truncf((float)w * rnd()/RAND_MAX);
- y = truncf((float)h * rnd()/RAND_MAX);
- v = truncf((float)w * rnd()/RAND_MAX * 0.2f);*/
- x = rndf() * w;
- y = rndf() * h;
-
- r = truncf((sizeFact*MIN(w,h)*rndf())+1.f);
-
- /*float r = 0.5f*w*rand()/RAND_MAX;
- float x = truncf(0.5f * w*rand()/RAND_MAX + r);
- float y = truncf(0.5f * w*rand()/RAND_MAX + r);*/
-
- vkvg_arc(ctx, x, y, r, 0, (float)M_PI * 2.0f);
- break;
- case SHAPE_TRIANGLE:
- case SHAPE_STAR:
- x = rndf() * w;
- y = rndf() * h;
- z = rndf() * sizeFact + 0.15f; //scale
-
- vkvg_move_to (ctx, x+star_points[0][0]*z, y+star_points[0][1]*z);
- for (int s=1; s<11; s++)
- vkvg_line_to (ctx, x+star_points[s][0]*z, y+star_points[s][1]*z);
- vkvg_close_path (ctx);
- break;
- case SHAPE_RANDOM:
- draw_random_shape(ctx, 1 + (rndf() * 4), sizeFact);
- break;
- }
+const int star_points[11][2] = {{0, 85}, {75, 75}, {100, 10}, {125, 75}, {200, 85}, {150, 125},
+ {160, 190}, {100, 150}, {40, 190}, {50, 125}, {0, 85}};
+void randomize_color(VkvgContext ctx) { vkvg_set_source_rgba(ctx, rndf(), rndf(), rndf(), rndf()); }
+void draw_random_shape(VkvgContext ctx, shape_t shape, float sizeFact) {
+ float w = (float)test_width;
+ float h = (float)test_height;
+
+ float x, y, z, v, r;
+
+ randomize_color(ctx);
+
+ switch (shape) {
+ case SHAPE_LINE:
+ x = rndf() * w;
+ y = rndf() * h;
+ z = rndf() * w;
+ v = rndf() * h;
+
+ vkvg_move_to(ctx, x, y);
+ vkvg_line_to(ctx, z, v);
+ vkvg_stroke(ctx);
+ break;
+ case SHAPE_RECTANGLE:
+ z = truncf((sizeFact * w * rndf()) + 1.f);
+ v = truncf((sizeFact * h * rndf()) + 1.f);
+ x = truncf((w - z) * rndf());
+ y = truncf((h - v) * rndf());
+
+ vkvg_rectangle(ctx, x + 1, y + 1, z, v);
+ break;
+ case SHAPE_ROUNDED_RECTANGLE:
+ z = truncf((sizeFact * w * rndf()) + 1.f);
+ v = truncf((sizeFact * h * rndf()) + 1.f);
+ x = truncf((w - z) * rndf());
+ y = truncf((h - v) * rndf());
+ r = truncf((0.2f * z * rndf()) + 1.f);
+
+ if ((r > v / 2) || (r > z / 2))
+ r = MIN(v / 2, z / 2);
+
+ vkvg_move_to(ctx, x, y + r);
+ vkvg_arc(ctx, x + r, y + r, r, (float)M_PI, (float)-M_PI_2);
+ vkvg_line_to(ctx, x + z - r, y);
+ vkvg_arc(ctx, x + z - r, y + r, r, (float)-M_PI_2, 0);
+ vkvg_line_to(ctx, x + z, y + v - r);
+ vkvg_arc(ctx, x + z - r, y + v - r, r, 0, (float)M_PI_2);
+ vkvg_line_to(ctx, x + r, y + v);
+ vkvg_arc(ctx, x + r, y + v - r, r, (float)M_PI_2, (float)M_PI);
+ vkvg_line_to(ctx, x, y + r);
+ vkvg_close_path(ctx);
+ break;
+ case SHAPE_CIRCLE:
+ /*x = truncf((float)w * rnd()/RAND_MAX);
+ y = truncf((float)h * rnd()/RAND_MAX);
+ v = truncf((float)w * rnd()/RAND_MAX * 0.2f);*/
+ x = rndf() * w;
+ y = rndf() * h;
+
+ r = truncf((sizeFact * MIN(w, h) * rndf()) + 1.f);
+
+ /*float r = 0.5f*w*rand()/RAND_MAX;
+ float x = truncf(0.5f * w*rand()/RAND_MAX + r);
+ float y = truncf(0.5f * w*rand()/RAND_MAX + r);*/
+
+ vkvg_arc(ctx, x, y, r, 0, (float)M_PI * 2.0f);
+ break;
+ case SHAPE_TRIANGLE:
+ case SHAPE_STAR:
+ x = rndf() * w;
+ y = rndf() * h;
+ z = rndf() * sizeFact + 0.15f; // scale
+
+ vkvg_move_to(ctx, x + star_points[0][0] * z, y + star_points[0][1] * z);
+ for (int s = 1; s < 11; s++)
+ vkvg_line_to(ctx, x + star_points[s][0] * z, y + star_points[s][1] * z);
+ vkvg_close_path(ctx);
+ break;
+ case SHAPE_RANDOM:
+ draw_random_shape(ctx, 1 + (rndf() * 4), sizeFact);
+ break;
+ }
}
-void draw_random_curve (VkvgContext ctx) {
- float w = (float)test_width;
- float h = (float)test_height;
-
- float x2 = w*rndf();
- float y2 = h*rndf();
- float cp_x1 = w*rndf();
- float cp_y1 = h*rndf();
- float cp_x2 = w*rndf();
- float cp_y2 = h*rndf();
-
- vkvg_curve_to(ctx, cp_x1, cp_y1, cp_x2, cp_y2, x2, y2);
+void draw_random_curve(VkvgContext ctx) {
+ float w = (float)test_width;
+ float h = (float)test_height;
+
+ float x2 = w * rndf();
+ float y2 = h * rndf();
+ float cp_x1 = w * rndf();
+ float cp_y1 = h * rndf();
+ float cp_x2 = w * rndf();
+ float cp_y2 = h * rndf();
+
+ vkvg_curve_to(ctx, cp_x1, cp_y1, cp_x2, cp_y2, x2, y2);
}
/*void draw_random_shape (VkvgContext ctx, shape_t shape) {
- float w = (float)test_width;
- float h = (float)test_height;
- randomize_color(ctx);
- float z = truncf((0.5f*w*rand()/RAND_MAX)+1.f);
- float v = truncf((0.5f*w*rand()/RAND_MAX)+1.f);
- float x = truncf((w-z)*rand()/RAND_MAX);
- float y = truncf((h-v)*rand()/RAND_MAX);
- vkvg_rectangle(ctx, x, y, z, v);
+ float w = (float)test_width;
+ float h = (float)test_height;
+ randomize_color(ctx);
+ float z = truncf((0.5f*w*rand()/RAND_MAX)+1.f);
+ float v = truncf((0.5f*w*rand()/RAND_MAX)+1.f);
+ float x = truncf((w-z)*rand()/RAND_MAX);
+ float y = truncf((h-v)*rand()/RAND_MAX);
+ vkvg_rectangle(ctx, x, y, z, v);
}*/
#include "vkh_presenter.h"
#include "vkh_phyinfo.h"
-#define M_PIF 3.14159265359f /* float pi */
-#define M_PIF_MULT_2 6.28318530718f
+#define M_PIF 3.14159265359f /* float pi */
+#define M_PIF_MULT_2 6.28318530718f
#ifndef M_PI
-# define M_PI 3.14159265358979323846 /* pi */
+#define M_PI 3.14159265358979323846 /* pi */
#endif
#ifndef M_PI_2
-# define M_PI_2 1.57079632679489661923 /* pi/2 */
+#define M_PI_2 1.57079632679489661923 /* pi/2 */
#endif
#ifndef MIN
-# define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
-# define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#define PERFORM_TEST(testName, argc, argv) perform_test(testName, #testName, argc, argv);
#if defined(_WIN32) || defined(_WIN64)
- #define WIN32_LEAN_AND_MEAN
- #define NOMINMAX
- #include <Windows.h> // Windows.h -> WinDef.h defines min() max()
-
- /*
- typedef uint16_t WORD ;
- typedef uint32_t DWORD;
-
- typedef struct _FILETIME {
- DWORD dwLowDateTime;
- DWORD dwHighDateTime;
- } FILETIME;
-
- typedef struct _SYSTEMTIME {
- WORD wYear;
- WORD wMonth;
- WORD wDayOfWeek;
- WORD wDay;
- WORD wHour;
- WORD wMinute;
- WORD wSecond;
- WORD wMilliseconds;
- } SYSTEMTIME, *PSYSTEMTIME;
- */
-
- // *sigh* Microsoft has this in winsock2.h because they are too lazy to put it in the standard location ... !?!?
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include <Windows.h> // Windows.h -> WinDef.h defines min() max()
+
+/*
+ typedef uint16_t WORD ;
+ typedef uint32_t DWORD;
+
+ typedef struct _FILETIME {
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+ } FILETIME;
+
+ typedef struct _SYSTEMTIME {
+ WORD wYear;
+ WORD wMonth;
+ WORD wDayOfWeek;
+ WORD wDay;
+ WORD wHour;
+ WORD wMinute;
+ WORD wSecond;
+ WORD wMilliseconds;
+ } SYSTEMTIME, *PSYSTEMTIME;
+*/
+
+// *sigh* Microsoft has this in winsock2.h because they are too lazy to put it in the standard location ... !?!?
#ifdef _MSC_VER
- typedef struct timeval {
- long tv_sec;
- long tv_usec;
- } timeval;
+typedef struct timeval {
+ long tv_sec;
+ long tv_usec;
+} timeval;
#endif
- // *sigh* no gettimeofday on Win32/Win64
- int gettimeofday(struct timeval * tp, void * tzp);
+// *sigh* no gettimeofday on Win32/Win64
+int gettimeofday(struct timeval *tp, void *tzp);
#else
- #include <sys/time.h>
+#include <sys/time.h>
#endif
typedef enum _shape_t {
- SHAPE_LINE,
- SHAPE_RECTANGLE,
- SHAPE_ROUNDED_RECTANGLE,
- SHAPE_CIRCLE,
- SHAPE_TRIANGLE,
- SHAPE_STAR,
- SHAPE_RANDOM,
+ SHAPE_LINE,
+ SHAPE_RECTANGLE,
+ SHAPE_ROUNDED_RECTANGLE,
+ SHAPE_CIRCLE,
+ SHAPE_TRIANGLE,
+ SHAPE_STAR,
+ SHAPE_RANDOM,
} shape_t;
extern uint32_t test_size;
extern uint32_t iterations;
extern uint32_t test_width;
extern uint32_t test_height;
-extern bool no_test_size;
+extern bool no_test_size;
extern float panX;
extern float panY;
extern float lastX;
extern float lastY;
extern float zoom;
-extern bool mouseDown;
+extern bool mouseDown;
-extern VkvgDevice device;
+extern VkvgDevice device;
extern VkvgSurface surf;
/* common context init for several tests */
-extern float dash_offset;
-extern float line_width;
+extern float dash_offset;
+extern float line_width;
extern vkvg_fill_rule_t fill_rule;
-extern vkvg_line_cap_t line_cap;
+extern vkvg_line_cap_t line_cap;
extern vkvg_line_join_t line_join;
-extern float dashes[];
-extern uint32_t dashes_count;
+extern float dashes[];
+extern uint32_t dashes_count;
VkvgContext _initCtx();
-void _parse_args (int argc, char* argv[]);
+void _parse_args(int argc, char *argv[]);
/*******************************/
-//run test in one step
-void perform_test (void(*testfunc)(), const char* testName, int argc, char *argv[]);
-void perform_test_onscreen (void(*testfunc)(void), const char *testName, int argc, char* argv[]);
-void perform_test_offscreen (void(*testfunc)(void), const char *testName, int argc, char* argv[]);
+// run test in one step
+void perform_test(void (*testfunc)(), const char *testName, int argc, char *argv[]);
+void perform_test_onscreen(void (*testfunc)(void), const char *testName, int argc, char *argv[]);
+void perform_test_offscreen(void (*testfunc)(void), const char *testName, int argc, char *argv[]);
-void randomize_color (VkvgContext ctx);
-void draw_random_shape (VkvgContext ctx, shape_t shape, float sizeFact);
-void draw_random_curve (VkvgContext ctx);
+void randomize_color(VkvgContext ctx);
+void draw_random_shape(VkvgContext ctx, shape_t shape, float sizeFact);
+void draw_random_curve(VkvgContext ctx);
-//run test in 3 step: init, run, clear.
-void init_test (uint32_t width, uint32_t height);
-void clear_test ();
+// run test in 3 step: init, run, clear.
+void init_test(uint32_t width, uint32_t height);
+void clear_test();
/* Platform specific includes */
#if defined(_TTHREAD_POSIX_)
- #include <signal.h>
- #include <sched.h>
- #include <unistd.h>
- #include <sys/time.h>
- #include <errno.h>
+#include <signal.h>
+#include <sched.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <errno.h>
#elif defined(_TTHREAD_WIN32_)
- #include <process.h>
- #include <sys/timeb.h>
+#include <process.h>
+#include <sys/timeb.h>
#endif
/* Standard, good-to-have defines */
#ifndef NULL
- #define NULL (void*)0
+#define NULL (void *)0
#endif
#ifndef TRUE
- #define TRUE 1
+#define TRUE 1
#endif
#ifndef FALSE
- #define FALSE 0
+#define FALSE 0
#endif
-int mtx_init(mtx_t *mtx, int type)
-{
+int mtx_init(mtx_t *mtx, int type) {
#if defined(_TTHREAD_WIN32_)
- mtx->mAlreadyLocked = FALSE;
- mtx->mRecursive = type & mtx_recursive;
- InitializeCriticalSection(&mtx->mHandle);
- return thrd_success;
+ mtx->mAlreadyLocked = FALSE;
+ mtx->mRecursive = type & mtx_recursive;
+ InitializeCriticalSection(&mtx->mHandle);
+ return thrd_success;
#else
- int ret;
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- if (type & mtx_recursive)
- {
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- }
- ret = pthread_mutex_init(mtx, &attr);
- pthread_mutexattr_destroy(&attr);
- return ret == 0 ? thrd_success : thrd_error;
+ int ret;
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ if (type & mtx_recursive) {
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ }
+ ret = pthread_mutex_init(mtx, &attr);
+ pthread_mutexattr_destroy(&attr);
+ return ret == 0 ? thrd_success : thrd_error;
#endif
}
-void mtx_destroy(mtx_t *mtx)
-{
+void mtx_destroy(mtx_t *mtx) {
#if defined(_TTHREAD_WIN32_)
- DeleteCriticalSection(&mtx->mHandle);
+ DeleteCriticalSection(&mtx->mHandle);
#else
- pthread_mutex_destroy(mtx);
+ pthread_mutex_destroy(mtx);
#endif
}
-int mtx_lock(mtx_t *mtx)
-{
+int mtx_lock(mtx_t *mtx) {
#if defined(_TTHREAD_WIN32_)
- EnterCriticalSection(&mtx->mHandle);
- if (!mtx->mRecursive)
- {
- while(mtx->mAlreadyLocked) Sleep(1000); /* Simulate deadlock... */
- mtx->mAlreadyLocked = TRUE;
- }
- return thrd_success;
+ EnterCriticalSection(&mtx->mHandle);
+ if (!mtx->mRecursive) {
+ while (mtx->mAlreadyLocked)
+ Sleep(1000); /* Simulate deadlock... */
+ mtx->mAlreadyLocked = TRUE;
+ }
+ return thrd_success;
#else
- return pthread_mutex_lock(mtx) == 0 ? thrd_success : thrd_error;
+ return pthread_mutex_lock(mtx) == 0 ? thrd_success : thrd_error;
#endif
}
-int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
-{
- /* FIXME! */
- (void)mtx;
- (void)ts;
- return thrd_error;
+int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) {
+ /* FIXME! */
+ (void)mtx;
+ (void)ts;
+ return thrd_error;
}
-int mtx_trylock(mtx_t *mtx)
-{
+int mtx_trylock(mtx_t *mtx) {
#if defined(_TTHREAD_WIN32_)
- int ret = TryEnterCriticalSection(&mtx->mHandle) ? thrd_success : thrd_busy;
- if ((!mtx->mRecursive) && (ret == thrd_success) && mtx->mAlreadyLocked)
- {
- LeaveCriticalSection(&mtx->mHandle);
- ret = thrd_busy;
- }
- return ret;
+ int ret = TryEnterCriticalSection(&mtx->mHandle) ? thrd_success : thrd_busy;
+ if ((!mtx->mRecursive) && (ret == thrd_success) && mtx->mAlreadyLocked) {
+ LeaveCriticalSection(&mtx->mHandle);
+ ret = thrd_busy;
+ }
+ return ret;
#else
- return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy;
+ return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy;
#endif
}
-int mtx_unlock(mtx_t *mtx)
-{
+int mtx_unlock(mtx_t *mtx) {
#if defined(_TTHREAD_WIN32_)
- mtx->mAlreadyLocked = FALSE;
- LeaveCriticalSection(&mtx->mHandle);
- return thrd_success;
+ mtx->mAlreadyLocked = FALSE;
+ LeaveCriticalSection(&mtx->mHandle);
+ return thrd_success;
#else
- return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;;
+ return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;
+ ;
#endif
}
#define _CONDITION_EVENT_ALL 1
#endif
-int cnd_init(cnd_t *cond)
-{
+int cnd_init(cnd_t *cond) {
#if defined(_TTHREAD_WIN32_)
- cond->mWaitersCount = 0;
+ cond->mWaitersCount = 0;
- /* Init critical section */
- InitializeCriticalSection(&cond->mWaitersCountLock);
+ /* Init critical section */
+ InitializeCriticalSection(&cond->mWaitersCountLock);
- /* Init events */
- cond->mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (cond->mEvents[_CONDITION_EVENT_ONE] == NULL)
- {
- cond->mEvents[_CONDITION_EVENT_ALL] = NULL;
- return thrd_error;
- }
- cond->mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (cond->mEvents[_CONDITION_EVENT_ALL] == NULL)
- {
- CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
- cond->mEvents[_CONDITION_EVENT_ONE] = NULL;
- return thrd_error;
- }
+ /* Init events */
+ cond->mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (cond->mEvents[_CONDITION_EVENT_ONE] == NULL) {
+ cond->mEvents[_CONDITION_EVENT_ALL] = NULL;
+ return thrd_error;
+ }
+ cond->mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (cond->mEvents[_CONDITION_EVENT_ALL] == NULL) {
+ CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
+ cond->mEvents[_CONDITION_EVENT_ONE] = NULL;
+ return thrd_error;
+ }
- return thrd_success;
+ return thrd_success;
#else
- return pthread_cond_init(cond, NULL) == 0 ? thrd_success : thrd_error;
+ return pthread_cond_init(cond, NULL) == 0 ? thrd_success : thrd_error;
#endif
}
-void cnd_destroy(cnd_t *cond)
-{
+void cnd_destroy(cnd_t *cond) {
#if defined(_TTHREAD_WIN32_)
- if (cond->mEvents[_CONDITION_EVENT_ONE] != NULL)
- {
- CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
- }
- if (cond->mEvents[_CONDITION_EVENT_ALL] != NULL)
- {
- CloseHandle(cond->mEvents[_CONDITION_EVENT_ALL]);
- }
- DeleteCriticalSection(&cond->mWaitersCountLock);
+ if (cond->mEvents[_CONDITION_EVENT_ONE] != NULL) {
+ CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
+ }
+ if (cond->mEvents[_CONDITION_EVENT_ALL] != NULL) {
+ CloseHandle(cond->mEvents[_CONDITION_EVENT_ALL]);
+ }
+ DeleteCriticalSection(&cond->mWaitersCountLock);
#else
- pthread_cond_destroy(cond);
+ pthread_cond_destroy(cond);
#endif
}
-int cnd_signal(cnd_t *cond)
-{
+int cnd_signal(cnd_t *cond) {
#if defined(_TTHREAD_WIN32_)
- int haveWaiters;
-
- /* Are there any waiters? */
- EnterCriticalSection(&cond->mWaitersCountLock);
- haveWaiters = (cond->mWaitersCount > 0);
- LeaveCriticalSection(&cond->mWaitersCountLock);
-
- /* If we have any waiting threads, send them a signal */
- if(haveWaiters)
- {
- if (SetEvent(cond->mEvents[_CONDITION_EVENT_ONE]) == 0)
- {
- return thrd_error;
+ int haveWaiters;
+
+ /* Are there any waiters? */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ haveWaiters = (cond->mWaitersCount > 0);
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* If we have any waiting threads, send them a signal */
+ if (haveWaiters) {
+ if (SetEvent(cond->mEvents[_CONDITION_EVENT_ONE]) == 0) {
+ return thrd_error;
+ }
}
- }
- return thrd_success;
+ return thrd_success;
#else
- return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
+ return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
#endif
}
-int cnd_broadcast(cnd_t *cond)
-{
+int cnd_broadcast(cnd_t *cond) {
#if defined(_TTHREAD_WIN32_)
- int haveWaiters;
-
- /* Are there any waiters? */
- EnterCriticalSection(&cond->mWaitersCountLock);
- haveWaiters = (cond->mWaitersCount > 0);
- LeaveCriticalSection(&cond->mWaitersCountLock);
-
- /* If we have any waiting threads, send them a signal */
- if(haveWaiters)
- {
- if (SetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
- {
- return thrd_error;
+ int haveWaiters;
+
+ /* Are there any waiters? */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ haveWaiters = (cond->mWaitersCount > 0);
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* If we have any waiting threads, send them a signal */
+ if (haveWaiters) {
+ if (SetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0) {
+ return thrd_error;
+ }
}
- }
- return thrd_success;
+ return thrd_success;
#else
- return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
+ return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
#endif
}
#if defined(_TTHREAD_WIN32_)
-static int _cnd_timedwait_win32(cnd_t *cond, mtx_t *mtx, DWORD timeout)
-{
- int result, lastWaiter;
-
- /* Increment number of waiters */
- EnterCriticalSection(&cond->mWaitersCountLock);
- ++ cond->mWaitersCount;
- LeaveCriticalSection(&cond->mWaitersCountLock);
-
- /* Release the mutex while waiting for the condition (will decrease
- the number of waiters when done)... */
- mtx_unlock(mtx);
-
- /* Wait for either event to become signaled due to cnd_signal() or
- cnd_broadcast() being called */
- result = WaitForMultipleObjects(2, cond->mEvents, FALSE, timeout);
- if (result == WAIT_TIMEOUT)
- {
- return thrd_timeout;
- }
- else if (result == (int)WAIT_FAILED)
- {
- return thrd_error;
- }
-
- /* Check if we are the last waiter */
- EnterCriticalSection(&cond->mWaitersCountLock);
- -- cond->mWaitersCount;
- lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) &&
- (cond->mWaitersCount == 0);
- LeaveCriticalSection(&cond->mWaitersCountLock);
-
- /* If we are the last waiter to be notified to stop waiting, reset the event */
- if (lastWaiter)
- {
- if (ResetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
- {
- return thrd_error;
+static int _cnd_timedwait_win32(cnd_t *cond, mtx_t *mtx, DWORD timeout) {
+ int result, lastWaiter;
+
+ /* Increment number of waiters */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ ++cond->mWaitersCount;
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* Release the mutex while waiting for the condition (will decrease
+ the number of waiters when done)... */
+ mtx_unlock(mtx);
+
+ /* Wait for either event to become signaled due to cnd_signal() or
+ cnd_broadcast() being called */
+ result = WaitForMultipleObjects(2, cond->mEvents, FALSE, timeout);
+ if (result == WAIT_TIMEOUT) {
+ return thrd_timeout;
+ } else if (result == (int)WAIT_FAILED) {
+ return thrd_error;
+ }
+
+ /* Check if we are the last waiter */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ --cond->mWaitersCount;
+ lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) && (cond->mWaitersCount == 0);
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* If we are the last waiter to be notified to stop waiting, reset the event */
+ if (lastWaiter) {
+ if (ResetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0) {
+ return thrd_error;
+ }
}
- }
- /* Re-acquire the mutex */
- mtx_lock(mtx);
+ /* Re-acquire the mutex */
+ mtx_lock(mtx);
- return thrd_success;
+ return thrd_success;
}
#endif
-int cnd_wait(cnd_t *cond, mtx_t *mtx)
-{
+int cnd_wait(cnd_t *cond, mtx_t *mtx) {
#if defined(_TTHREAD_WIN32_)
- return _cnd_timedwait_win32(cond, mtx, INFINITE);
+ return _cnd_timedwait_win32(cond, mtx, INFINITE);
#else
- return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error;
+ return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error;
#endif
}
-int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
-{
+int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts) {
#if defined(_TTHREAD_WIN32_)
- struct timespec now;
- if (clock_gettime(CLOCK_REALTIME, &now) == 0)
- {
- DWORD delta = (DWORD) ((ts->tv_sec - now.tv_sec) * 1000 +
- (ts->tv_nsec - now.tv_nsec + 500000) / 1000000);
- return _cnd_timedwait_win32(cond, mtx, delta);
- }
- else
- return thrd_error;
+ struct timespec now;
+ if (clock_gettime(CLOCK_REALTIME, &now) == 0) {
+ DWORD delta = (DWORD)((ts->tv_sec - now.tv_sec) * 1000 + (ts->tv_nsec - now.tv_nsec + 500000) / 1000000);
+ return _cnd_timedwait_win32(cond, mtx, delta);
+ } else
+ return thrd_error;
#else
- int ret;
- ret = pthread_cond_timedwait(cond, mtx, ts);
- if (ret == ETIMEDOUT)
- {
- return thrd_timeout;
- }
- return ret == 0 ? thrd_success : thrd_error;
+ int ret;
+ ret = pthread_cond_timedwait(cond, mtx, ts);
+ if (ret == ETIMEDOUT) {
+ return thrd_timeout;
+ }
+ return ret == 0 ? thrd_success : thrd_error;
#endif
}
-
/** Information to pass to the new thread (what to run). */
typedef struct {
- thrd_start_t mFunction; /**< Pointer to the function to be executed. */
- void * mArg; /**< Function argument for the thread function. */
+ thrd_start_t mFunction; /**< Pointer to the function to be executed. */
+ void *mArg; /**< Function argument for the thread function. */
} _thread_start_info;
/* Thread wrapper function. */
#if defined(_TTHREAD_WIN32_)
-static unsigned WINAPI _thrd_wrapper_function(void * aArg)
+static unsigned WINAPI _thrd_wrapper_function(void *aArg)
#elif defined(_TTHREAD_POSIX_)
-static void * _thrd_wrapper_function(void * aArg)
+static void *_thrd_wrapper_function(void *aArg)
#endif
{
- thrd_start_t fun;
- void *arg;
- int res;
+ thrd_start_t fun;
+ void *arg;
+ int res;
#if defined(_TTHREAD_POSIX_)
- void *pres;
+ void *pres;
#endif
- /* Get thread startup information */
- _thread_start_info *ti = (_thread_start_info *) aArg;
- fun = ti->mFunction;
- arg = ti->mArg;
+ /* Get thread startup information */
+ _thread_start_info *ti = (_thread_start_info *)aArg;
+ fun = ti->mFunction;
+ arg = ti->mArg;
- /* The thread is responsible for freeing the startup information */
- free((void *)ti);
+ /* The thread is responsible for freeing the startup information */
+ free((void *)ti);
- /* Call the actual client thread function */
- res = fun(arg);
+ /* Call the actual client thread function */
+ res = fun(arg);
#if defined(_TTHREAD_WIN32_)
- return res;
+ return res;
#else
- pres = malloc(sizeof(int));
- if (pres != NULL)
- {
- *(int*)pres = res;
- }
- return pres;
+ pres = malloc(sizeof(int));
+ if (pres != NULL) {
+ *(int *)pres = res;
+ }
+ return pres;
#endif
}
-int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
-{
- /* Fill out the thread startup information (passed to the thread wrapper,
- which will eventually free it) */
- _thread_start_info* ti = (_thread_start_info*)malloc(sizeof(_thread_start_info));
- if (ti == NULL)
- {
- return thrd_nomem;
- }
- ti->mFunction = func;
- ti->mArg = arg;
-
- /* Create the thread */
+int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) {
+ /* Fill out the thread startup information (passed to the thread wrapper,
+ which will eventually free it) */
+ _thread_start_info *ti = (_thread_start_info *)malloc(sizeof(_thread_start_info));
+ if (ti == NULL) {
+ return thrd_nomem;
+ }
+ ti->mFunction = func;
+ ti->mArg = arg;
+
+ /* Create the thread */
#if defined(_TTHREAD_WIN32_)
- *thr = (HANDLE)_beginthreadex(NULL, 0, _thrd_wrapper_function, (void *)ti, 0, NULL);
+ *thr = (HANDLE)_beginthreadex(NULL, 0, _thrd_wrapper_function, (void *)ti, 0, NULL);
#elif defined(_TTHREAD_POSIX_)
- if(pthread_create(thr, NULL, _thrd_wrapper_function, (void *)ti) != 0)
- {
- *thr = 0;
- }
+ if (pthread_create(thr, NULL, _thrd_wrapper_function, (void *)ti) != 0) {
+ *thr = 0;
+ }
#endif
- /* Did we fail to create the thread? */
- if(!*thr)
- {
- free(ti);
- return thrd_error;
- }
+ /* Did we fail to create the thread? */
+ if (!*thr) {
+ free(ti);
+ return thrd_error;
+ }
- return thrd_success;
+ return thrd_success;
}
-thrd_t thrd_current(void)
-{
+thrd_t thrd_current(void) {
#if defined(_TTHREAD_WIN32_)
- return GetCurrentThread();
+ return GetCurrentThread();
#else
- return pthread_self();
+ return pthread_self();
#endif
}
-int thrd_detach(thrd_t thr)
-{
- /* FIXME! */
- (void)thr;
- return thrd_error;
+int thrd_detach(thrd_t thr) {
+ /* FIXME! */
+ (void)thr;
+ return thrd_error;
}
-int thrd_equal(thrd_t thr0, thrd_t thr1)
-{
+int thrd_equal(thrd_t thr0, thrd_t thr1) {
#if defined(_TTHREAD_WIN32_)
- return thr0 == thr1;
+ return thr0 == thr1;
#else
- return pthread_equal(thr0, thr1);
+ return pthread_equal(thr0, thr1);
#endif
}
-void thrd_exit(int res)
-{
+void thrd_exit(int res) {
#if defined(_TTHREAD_WIN32_)
- ExitThread(res);
+ ExitThread(res);
#else
- void *pres = malloc(sizeof(int));
- if (pres != NULL)
- {
- *(int*)pres = res;
- }
- pthread_exit(pres);
+ void *pres = malloc(sizeof(int));
+ if (pres != NULL) {
+ *(int *)pres = res;
+ }
+ pthread_exit(pres);
#endif
}
-int thrd_join(thrd_t thr, int *res)
-{
+int thrd_join(thrd_t thr, int *res) {
#if defined(_TTHREAD_WIN32_)
- if (WaitForSingleObject(thr, INFINITE) == WAIT_FAILED)
- {
- return thrd_error;
- }
- if (res != NULL)
- {
- DWORD dwRes;
- GetExitCodeThread(thr, &dwRes);
- *res = dwRes;
- }
+ if (WaitForSingleObject(thr, INFINITE) == WAIT_FAILED) {
+ return thrd_error;
+ }
+ if (res != NULL) {
+ DWORD dwRes;
+ GetExitCodeThread(thr, &dwRes);
+ *res = dwRes;
+ }
#elif defined(_TTHREAD_POSIX_)
- void *pres;
- int ires = 0;
- if (pthread_join(thr, &pres) != 0)
- {
- return thrd_error;
- }
- if (pres != NULL)
- {
- ires = *(int*)pres;
- free(pres);
- }
- if (res != NULL)
- {
- *res = ires;
- }
-#endif
- return thrd_success;
+ void *pres;
+ int ires = 0;
+ if (pthread_join(thr, &pres) != 0) {
+ return thrd_error;
+ }
+ if (pres != NULL) {
+ ires = *(int *)pres;
+ free(pres);
+ }
+ if (res != NULL) {
+ *res = ires;
+ }
+#endif
+ return thrd_success;
}
-int thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
-{
- struct timespec now;
+int thrd_sleep(const struct timespec *time_point, struct timespec *remaining) {
+ struct timespec now;
#if defined(_TTHREAD_WIN32_)
- DWORD delta;
+ DWORD delta;
#else
- long delta;
+ long delta;
#endif
- /* Get the current time */
- if (clock_gettime(CLOCK_REALTIME, &now) != 0)
- return -2; // FIXME: Some specific error code?
+ /* Get the current time */
+ if (clock_gettime(CLOCK_REALTIME, &now) != 0)
+ return -2; // FIXME: Some specific error code?
#if defined(_TTHREAD_WIN32_)
- /* Delta in milliseconds */
- delta = (DWORD) ((time_point->tv_sec - now.tv_sec) * 1000 +
- (time_point->tv_nsec - now.tv_nsec + 500000) / 1000000);
- if (delta > 0)
- {
- Sleep(delta);
- }
+ /* Delta in milliseconds */
+ delta = (DWORD)((time_point->tv_sec - now.tv_sec) * 1000 + (time_point->tv_nsec - now.tv_nsec + 500000) / 1000000);
+ if (delta > 0) {
+ Sleep(delta);
+ }
#else
- /* Delta in microseconds */
- delta = (time_point->tv_sec - now.tv_sec) * 1000000L +
- (time_point->tv_nsec - now.tv_nsec + 500L) / 1000L;
-
- /* On some systems, the usleep argument must be < 1000000 */
- while (delta > 999999L)
- {
- usleep(999999);
- delta -= 999999L;
- }
- if (delta > 0L)
- {
- usleep((useconds_t)delta);
- }
-#endif
-
- /* We don't support waking up prematurely (yet) */
- if (remaining)
- {
- remaining->tv_sec = 0;
- remaining->tv_nsec = 0;
- }
- return 0;
+ /* Delta in microseconds */
+ delta = (time_point->tv_sec - now.tv_sec) * 1000000L + (time_point->tv_nsec - now.tv_nsec + 500L) / 1000L;
+
+ /* On some systems, the usleep argument must be < 1000000 */
+ while (delta > 999999L) {
+ usleep(999999);
+ delta -= 999999L;
+ }
+ if (delta > 0L) {
+ usleep((useconds_t)delta);
+ }
+#endif
+
+ /* We don't support waking up prematurely (yet) */
+ if (remaining) {
+ remaining->tv_sec = 0;
+ remaining->tv_nsec = 0;
+ }
+ return 0;
}
-void thrd_yield(void)
-{
+void thrd_yield(void) {
#if defined(_TTHREAD_WIN32_)
- Sleep(0);
+ Sleep(0);
#else
- sched_yield();
+ sched_yield();
#endif
}
-int tss_create(tss_t *key, tss_dtor_t dtor)
-{
+int tss_create(tss_t *key, tss_dtor_t dtor) {
#if defined(_TTHREAD_WIN32_)
- /* FIXME: The destructor function is not supported yet... */
- if (dtor != NULL)
- {
- return thrd_error;
- }
- *key = TlsAlloc();
- if (*key == TLS_OUT_OF_INDEXES)
- {
- return thrd_error;
- }
+ /* FIXME: The destructor function is not supported yet... */
+ if (dtor != NULL) {
+ return thrd_error;
+ }
+ *key = TlsAlloc();
+ if (*key == TLS_OUT_OF_INDEXES) {
+ return thrd_error;
+ }
#else
- if (pthread_key_create(key, dtor) != 0)
- {
- return thrd_error;
- }
+ if (pthread_key_create(key, dtor) != 0) {
+ return thrd_error;
+ }
#endif
- return thrd_success;
+ return thrd_success;
}
-void tss_delete(tss_t key)
-{
+void tss_delete(tss_t key) {
#if defined(_TTHREAD_WIN32_)
- TlsFree(key);
+ TlsFree(key);
#else
- pthread_key_delete(key);
+ pthread_key_delete(key);
#endif
}
-void *tss_get(tss_t key)
-{
+void *tss_get(tss_t key) {
#if defined(_TTHREAD_WIN32_)
- return TlsGetValue(key);
+ return TlsGetValue(key);
#else
- return pthread_getspecific(key);
+ return pthread_getspecific(key);
#endif
}
-int tss_set(tss_t key, void *val)
-{
+int tss_set(tss_t key, void *val) {
#if defined(_TTHREAD_WIN32_)
- if (TlsSetValue(key, val) == 0)
- {
- return thrd_error;
- }
+ if (TlsSetValue(key, val) == 0) {
+ return thrd_error;
+ }
#else
- if (pthread_setspecific(key, val) != 0)
- {
- return thrd_error;
- }
+ if (pthread_setspecific(key, val) != 0) {
+ return thrd_error;
+ }
#endif
- return thrd_success;
+ return thrd_success;
}
#if defined(_TTHREAD_EMULATE_CLOCK_GETTIME_)
-int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts)
-{
+int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts) {
#if defined(_TTHREAD_WIN32_)
- struct _timeb tb;
- _ftime(&tb);
- ts->tv_sec = (time_t)tb.time;
- ts->tv_nsec = 1000000L * (long)tb.millitm;
+ struct _timeb tb;
+ _ftime(&tb);
+ ts->tv_sec = (time_t)tb.time;
+ ts->tv_nsec = 1000000L * (long)tb.millitm;
#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- ts->tv_sec = (time_t)tv.tv_sec;
- ts->tv_nsec = 1000L * (long)tv.tv_usec;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ ts->tv_sec = (time_t)tv.tv_sec;
+ ts->tv_nsec = 1000L * (long)tv.tv_usec;
#endif
- return 0;
+ return 0;
}
#endif // _TTHREAD_EMULATE_CLOCK_GETTIME_
-
#define _TINYCTHREAD_H_
/**
-* @file
-* @mainpage TinyCThread API Reference
-*
-* @section intro_sec Introduction
-* TinyCThread is a minimal, portable implementation of basic threading
-* classes for C.
-*
-* They closely mimic the functionality and naming of the C11 standard, and
-* should be easily replaceable with the corresponding standard variants.
-*
-* @section port_sec Portability
-* The Win32 variant uses the native Win32 API for implementing the thread
-* classes, while for other systems, the POSIX threads API (pthread) is used.
-*
-* @section misc_sec Miscellaneous
-* The following special keywords are available: #_Thread_local.
-*
-* For more detailed information, browse the different sections of this
-* documentation. A good place to start is:
-* tinycthread.h.
-*/
+ * @file
+ * @mainpage TinyCThread API Reference
+ *
+ * @section intro_sec Introduction
+ * TinyCThread is a minimal, portable implementation of basic threading
+ * classes for C.
+ *
+ * They closely mimic the functionality and naming of the C11 standard, and
+ * should be easily replaceable with the corresponding standard variants.
+ *
+ * @section port_sec Portability
+ * The Win32 variant uses the native Win32 API for implementing the thread
+ * classes, while for other systems, the POSIX threads API (pthread) is used.
+ *
+ * @section misc_sec Miscellaneous
+ * The following special keywords are available: #_Thread_local.
+ *
+ * For more detailed information, browse the different sections of this
+ * documentation. A good place to start is:
+ * tinycthread.h.
+ */
/* Which platform are we on? */
#if !defined(_TTHREAD_PLATFORM_DEFINED_)
- #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
- #define _TTHREAD_WIN32_
- #else
- #define _TTHREAD_POSIX_
- #endif
- #define _TTHREAD_PLATFORM_DEFINED_
+#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
+#define _TTHREAD_WIN32_
+#else
+#define _TTHREAD_POSIX_
+#endif
+#define _TTHREAD_PLATFORM_DEFINED_
#endif
/* Activate some POSIX functionality (e.g. clock_gettime and recursive mutexes) */
#if defined(_TTHREAD_POSIX_)
- #undef _FEATURES_H
- #if !defined(_GNU_SOURCE)
- #define _GNU_SOURCE
- #endif
- #if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L)
- #undef _POSIX_C_SOURCE
- #define _POSIX_C_SOURCE 199309L
- #endif
- #if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500)
- #undef _XOPEN_SOURCE
- #define _XOPEN_SOURCE 500
- #endif
+#undef _FEATURES_H
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE
+#endif
+#if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L)
+#undef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 199309L
+#endif
+#if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500)
+#undef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 500
+#endif
#endif
/* Generic includes */
/* Platform specific includes */
#if defined(_TTHREAD_POSIX_)
- #include <sys/time.h>
- #include <pthread.h>
+#include <sys/time.h>
+#include <pthread.h>
#elif defined(_TTHREAD_WIN32_)
- #ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN
- #define __UNDEF_LEAN_AND_MEAN
- #endif
- #include <windows.h>
- #ifdef __UNDEF_LEAN_AND_MEAN
- #undef WIN32_LEAN_AND_MEAN
- #undef __UNDEF_LEAN_AND_MEAN
- #endif
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#define __UNDEF_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#ifdef __UNDEF_LEAN_AND_MEAN
+#undef WIN32_LEAN_AND_MEAN
+#undef __UNDEF_LEAN_AND_MEAN
+#endif
#endif
/* Workaround for missing TIME_UTC: If time.h doesn't provide TIME_UTC,
the only other supported time specifier: CLOCK_REALTIME (and if that fails,
we're probably emulating clock_gettime anyway, so anything goes). */
#ifndef TIME_UTC
- #ifdef CLOCK_REALTIME
- #define TIME_UTC CLOCK_REALTIME
- #else
- #define TIME_UTC 0
- #endif
+#ifdef CLOCK_REALTIME
+#define TIME_UTC CLOCK_REALTIME
+#else
+#define TIME_UTC 0
+#endif
#endif
/* Workaround for missing clock_gettime (most Windows compilers, afaik) */
/* Emulate struct timespec */
#if defined(_TTHREAD_WIN32_)
struct _ttherad_timespec {
- time_t tv_sec;
- long tv_nsec;
+ time_t tv_sec;
+ long tv_nsec;
};
#define timespec _ttherad_timespec
#endif
int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
#define clock_gettime _tthread_clock_gettime
#ifndef CLOCK_REALTIME
- #define CLOCK_REALTIME 0
+#define CLOCK_REALTIME 0
#endif
#endif
-
/** TinyCThread version (major number). */
#define TINYCTHREAD_VERSION_MAJOR 1
/** TinyCThread version (minor number). */
#define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR)
/**
-* @def _Thread_local
-* Thread local storage keyword.
-* A variable that is declared with the @c _Thread_local keyword makes the
-* value of the variable local to each thread (known as thread-local storage,
-* or TLS). Example usage:
-* @code
-* // This variable is local to each thread.
-* _Thread_local int variable;
-* @endcode
-* @note The @c _Thread_local keyword is a macro that maps to the corresponding
-* compiler directive (e.g. @c __declspec(thread)).
-* @note This directive is currently not supported on Mac OS X (it will give
-* a compiler error), since compile-time TLS is not supported in the Mac OS X
-* executable format. Also, some older versions of MinGW (before GCC 4.x) do
-* not support this directive.
-* @hideinitializer
-*/
+ * @def _Thread_local
+ * Thread local storage keyword.
+ * A variable that is declared with the @c _Thread_local keyword makes the
+ * value of the variable local to each thread (known as thread-local storage,
+ * or TLS). Example usage:
+ * @code
+ * // This variable is local to each thread.
+ * _Thread_local int variable;
+ * @endcode
+ * @note The @c _Thread_local keyword is a macro that maps to the corresponding
+ * compiler directive (e.g. @c __declspec(thread)).
+ * @note This directive is currently not supported on Mac OS X (it will give
+ * a compiler error), since compile-time TLS is not supported in the Mac OS X
+ * executable format. Also, some older versions of MinGW (before GCC 4.x) do
+ * not support this directive.
+ * @hideinitializer
+ */
/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 */
#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
- #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
- #define _Thread_local __thread
- #else
- #define _Thread_local __declspec(thread)
- #endif
+#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+#define _Thread_local __thread
+#else
+#define _Thread_local __declspec(thread)
+#endif
#endif
/* Macros */
#define TSS_DTOR_ITERATIONS 0
/* Function return values */
-#define thrd_error 0 /**< The requested operation failed */
-#define thrd_success 1 /**< The requested operation succeeded */
-#define thrd_timeout 2 /**< The time specified in the call was reached without acquiring the requested resource */
-#define thrd_busy 3 /**< The requested operation failed because a tesource requested by a test and return function is already in use */
-#define thrd_nomem 4 /**< The requested operation failed because it was unable to allocate memory */
+#define thrd_error 0 /**< The requested operation failed */
+#define thrd_success 1 /**< The requested operation succeeded */
+#define thrd_timeout 2 /**< The time specified in the call was reached without acquiring the requested resource */
+#define thrd_busy \
+ 3 /**< The requested operation failed because a tesource requested by a test and return function is already in use \
+ */
+#define thrd_nomem 4 /**< The requested operation failed because it was unable to allocate memory */
/* Mutex types */
#define mtx_plain 1
/* Mutex */
#if defined(_TTHREAD_WIN32_)
typedef struct {
- CRITICAL_SECTION mHandle; /* Critical section handle */
- int mAlreadyLocked; /* TRUE if the mutex is already locked */
- int mRecursive; /* TRUE if the mutex is recursive */
+ CRITICAL_SECTION mHandle; /* Critical section handle */
+ int mAlreadyLocked; /* TRUE if the mutex is already locked */
+ int mRecursive; /* TRUE if the mutex is recursive */
} mtx_t;
#else
typedef pthread_mutex_t mtx_t;
#endif
/** Create a mutex object.
-* @param mtx A mutex object.
-* @param type Bit-mask that must have one of the following six values:
-* @li @c mtx_plain for a simple non-recursive mutex
-* @li @c mtx_timed for a non-recursive mutex that supports timeout
-* @li @c mtx_try for a non-recursive mutex that supports test and return
-* @li @c mtx_plain | @c mtx_recursive (same as @c mtx_plain, but recursive)
-* @li @c mtx_timed | @c mtx_recursive (same as @c mtx_timed, but recursive)
-* @li @c mtx_try | @c mtx_recursive (same as @c mtx_try, but recursive)
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * @param mtx A mutex object.
+ * @param type Bit-mask that must have one of the following six values:
+ * @li @c mtx_plain for a simple non-recursive mutex
+ * @li @c mtx_timed for a non-recursive mutex that supports timeout
+ * @li @c mtx_try for a non-recursive mutex that supports test and return
+ * @li @c mtx_plain | @c mtx_recursive (same as @c mtx_plain, but recursive)
+ * @li @c mtx_timed | @c mtx_recursive (same as @c mtx_timed, but recursive)
+ * @li @c mtx_try | @c mtx_recursive (same as @c mtx_try, but recursive)
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int mtx_init(mtx_t *mtx, int type);
/** Release any resources used by the given mutex.
-* @param mtx A mutex object.
-*/
+ * @param mtx A mutex object.
+ */
void mtx_destroy(mtx_t *mtx);
/** Lock the given mutex.
-* Blocks until the given mutex can be locked. If the mutex is non-recursive, and
-* the calling thread already has a lock on the mutex, this call will block
-* forever.
-* @param mtx A mutex object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * Blocks until the given mutex can be locked. If the mutex is non-recursive, and
+ * the calling thread already has a lock on the mutex, this call will block
+ * forever.
+ * @param mtx A mutex object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int mtx_lock(mtx_t *mtx);
/** NOT YET IMPLEMENTED.
-*/
+ */
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
/** Try to lock the given mutex.
-* The specified mutex shall support either test and return or timeout. If the
-* mutex is already locked, the function returns without blocking.
-* @param mtx A mutex object.
-* @return @ref thrd_success on success, or @ref thrd_busy if the resource
-* requested is already in use, or @ref thrd_error if the request could not be
-* honored.
-*/
+ * The specified mutex shall support either test and return or timeout. If the
+ * mutex is already locked, the function returns without blocking.
+ * @param mtx A mutex object.
+ * @return @ref thrd_success on success, or @ref thrd_busy if the resource
+ * requested is already in use, or @ref thrd_error if the request could not be
+ * honored.
+ */
int mtx_trylock(mtx_t *mtx);
/** Unlock the given mutex.
-* @param mtx A mutex object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * @param mtx A mutex object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int mtx_unlock(mtx_t *mtx);
/* Condition variable */
#if defined(_TTHREAD_WIN32_)
typedef struct {
- HANDLE mEvents[2]; /* Signal and broadcast event HANDLEs. */
- unsigned int mWaitersCount; /* Count of the number of waiters. */
- CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */
+ HANDLE mEvents[2]; /* Signal and broadcast event HANDLEs. */
+ unsigned int mWaitersCount; /* Count of the number of waiters. */
+ CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */
} cnd_t;
#else
-typedef pthread_cond_t cnd_t;
+typedef pthread_cond_t cnd_t;
#endif
/** Create a condition variable object.
-* @param cond A condition variable object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * @param cond A condition variable object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int cnd_init(cnd_t *cond);
/** Release any resources used by the given condition variable.
-* @param cond A condition variable object.
-*/
+ * @param cond A condition variable object.
+ */
void cnd_destroy(cnd_t *cond);
/** Signal a condition variable.
-* Unblocks one of the threads that are blocked on the given condition variable
-* at the time of the call. If no threads are blocked on the condition variable
-* at the time of the call, the function does nothing and return success.
-* @param cond A condition variable object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * Unblocks one of the threads that are blocked on the given condition variable
+ * at the time of the call. If no threads are blocked on the condition variable
+ * at the time of the call, the function does nothing and return success.
+ * @param cond A condition variable object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int cnd_signal(cnd_t *cond);
/** Broadcast a condition variable.
-* Unblocks all of the threads that are blocked on the given condition variable
-* at the time of the call. If no threads are blocked on the condition variable
-* at the time of the call, the function does nothing and return success.
-* @param cond A condition variable object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * Unblocks all of the threads that are blocked on the given condition variable
+ * at the time of the call. If no threads are blocked on the condition variable
+ * at the time of the call, the function does nothing and return success.
+ * @param cond A condition variable object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int cnd_broadcast(cnd_t *cond);
/** Wait for a condition variable to become signaled.
-* The function atomically unlocks the given mutex and endeavors to block until
-* the given condition variable is signaled by a call to cnd_signal or to
-* cnd_broadcast. When the calling thread becomes unblocked it locks the mutex
-* before it returns.
-* @param cond A condition variable object.
-* @param mtx A mutex object.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * The function atomically unlocks the given mutex and endeavors to block until
+ * the given condition variable is signaled by a call to cnd_signal or to
+ * cnd_broadcast. When the calling thread becomes unblocked it locks the mutex
+ * before it returns.
+ * @param cond A condition variable object.
+ * @param mtx A mutex object.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int cnd_wait(cnd_t *cond, mtx_t *mtx);
/** Wait for a condition variable to become signaled.
-* The function atomically unlocks the given mutex and endeavors to block until
-* the given condition variable is signaled by a call to cnd_signal or to
-* cnd_broadcast, or until after the specified time. When the calling thread
-* becomes unblocked it locks the mutex before it returns.
-* @param cond A condition variable object.
-* @param mtx A mutex object.
-* @param xt A point in time at which the request will time out (absolute time).
-* @return @ref thrd_success upon success, or @ref thrd_timeout if the time
-* specified in the call was reached without acquiring the requested resource, or
-* @ref thrd_error if the request could not be honored.
-*/
+ * The function atomically unlocks the given mutex and endeavors to block until
+ * the given condition variable is signaled by a call to cnd_signal or to
+ * cnd_broadcast, or until after the specified time. When the calling thread
+ * becomes unblocked it locks the mutex before it returns.
+ * @param cond A condition variable object.
+ * @param mtx A mutex object.
+ * @param xt A point in time at which the request will time out (absolute time).
+ * @return @ref thrd_success upon success, or @ref thrd_timeout if the time
+ * specified in the call was reached without acquiring the requested resource, or
+ * @ref thrd_error if the request could not be honored.
+ */
int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts);
/* Thread */
#if defined(_TTHREAD_WIN32_)
typedef HANDLE thrd_t;
#else
-typedef pthread_t thrd_t;
+typedef pthread_t thrd_t;
#endif
/** Thread start function.
-* Any thread that is started with the @ref thrd_create() function must be
-* started through a function of this type.
-* @param arg The thread argument (the @c arg argument of the corresponding
-* @ref thrd_create() call).
-* @return The thread return value, which can be obtained by another thread
-* by using the @ref thrd_join() function.
-*/
+ * Any thread that is started with the @ref thrd_create() function must be
+ * started through a function of this type.
+ * @param arg The thread argument (the @c arg argument of the corresponding
+ * @ref thrd_create() call).
+ * @return The thread return value, which can be obtained by another thread
+ * by using the @ref thrd_join() function.
+ */
typedef int (*thrd_start_t)(void *arg);
/** Create a new thread.
-* @param thr Identifier of the newly created thread.
-* @param func A function pointer to the function that will be executed in
-* the new thread.
-* @param arg An argument to the thread function.
-* @return @ref thrd_success on success, or @ref thrd_nomem if no memory could
-* be allocated for the thread requested, or @ref thrd_error if the request
-* could not be honored.
-* @note A thread’s identifier may be reused for a different thread once the
-* original thread has exited and either been detached or joined to another
-* thread.
-*/
+ * @param thr Identifier of the newly created thread.
+ * @param func A function pointer to the function that will be executed in
+ * the new thread.
+ * @param arg An argument to the thread function.
+ * @return @ref thrd_success on success, or @ref thrd_nomem if no memory could
+ * be allocated for the thread requested, or @ref thrd_error if the request
+ * could not be honored.
+ * @note A thread’s identifier may be reused for a different thread once the
+ * original thread has exited and either been detached or joined to another
+ * thread.
+ */
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
/** Identify the calling thread.
-* @return The identifier of the calling thread.
-*/
+ * @return The identifier of the calling thread.
+ */
thrd_t thrd_current(void);
/** NOT YET IMPLEMENTED.
-*/
+ */
int thrd_detach(thrd_t thr);
/** Compare two thread identifiers.
-* The function determines if two thread identifiers refer to the same thread.
-* @return Zero if the two thread identifiers refer to different threads.
-* Otherwise a nonzero value is returned.
-*/
+ * The function determines if two thread identifiers refer to the same thread.
+ * @return Zero if the two thread identifiers refer to different threads.
+ * Otherwise a nonzero value is returned.
+ */
int thrd_equal(thrd_t thr0, thrd_t thr1);
/** Terminate execution of the calling thread.
-* @param res Result code of the calling thread.
-*/
+ * @param res Result code of the calling thread.
+ */
void thrd_exit(int res);
/** Wait for a thread to terminate.
-* The function joins the given thread with the current thread by blocking
-* until the other thread has terminated.
-* @param thr The thread to join with.
-* @param res If this pointer is not NULL, the function will store the result
-* code of the given thread in the integer pointed to by @c res.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * The function joins the given thread with the current thread by blocking
+ * until the other thread has terminated.
+ * @param thr The thread to join with.
+ * @param res If this pointer is not NULL, the function will store the result
+ * code of the given thread in the integer pointed to by @c res.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int thrd_join(thrd_t thr, int *res);
/** Put the calling thread to sleep.
-* Suspend execution of the calling thread.
-* @param time_point A point in time at which the thread will resume (absolute time).
-* @param remaining If non-NULL, this parameter will hold the remaining time until
-* time_point upon return. This will typically be zero, but if
-* the thread was woken up by a signal that is not ignored before
-* time_point was reached @c remaining will hold a positive
-* time.
-* @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
-*/
+ * Suspend execution of the calling thread.
+ * @param time_point A point in time at which the thread will resume (absolute time).
+ * @param remaining If non-NULL, this parameter will hold the remaining time until
+ * time_point upon return. This will typically be zero, but if
+ * the thread was woken up by a signal that is not ignored before
+ * time_point was reached @c remaining will hold a positive
+ * time.
+ * @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
+ */
int thrd_sleep(const struct timespec *time_point, struct timespec *remaining);
/** Yield execution to another thread.
-* Permit other threads to run, even if the current thread would ordinarily
-* continue to run.
-*/
+ * Permit other threads to run, even if the current thread would ordinarily
+ * continue to run.
+ */
void thrd_yield(void);
/* Thread local storage */
#if defined(_TTHREAD_WIN32_)
typedef DWORD tss_t;
#else
-typedef pthread_key_t tss_t;
+typedef pthread_key_t tss_t;
#endif
/** Destructor function for a thread-specific storage.
-* @param val The value of the destructed thread-specific storage.
-*/
+ * @param val The value of the destructed thread-specific storage.
+ */
typedef void (*tss_dtor_t)(void *val);
/** Create a thread-specific storage.
-* @param key The unique key identifier that will be set if the function is
-* successful.
-* @param dtor Destructor function. This can be NULL.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-* @note The destructor function is not supported under Windows. If @c dtor is
-* not NULL when calling this function under Windows, the function will fail
-* and return @ref thrd_error.
-*/
+ * @param key The unique key identifier that will be set if the function is
+ * successful.
+ * @param dtor Destructor function. This can be NULL.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ * @note The destructor function is not supported under Windows. If @c dtor is
+ * not NULL when calling this function under Windows, the function will fail
+ * and return @ref thrd_error.
+ */
int tss_create(tss_t *key, tss_dtor_t dtor);
/** Delete a thread-specific storage.
-* The function releases any resources used by the given thread-specific
-* storage.
-* @param key The key that shall be deleted.
-*/
+ * The function releases any resources used by the given thread-specific
+ * storage.
+ * @param key The key that shall be deleted.
+ */
void tss_delete(tss_t key);
/** Get the value for a thread-specific storage.
-* @param key The thread-specific storage identifier.
-* @return The value for the current thread held in the given thread-specific
-* storage.
-*/
+ * @param key The thread-specific storage identifier.
+ * @return The value for the current thread held in the given thread-specific
+ * storage.
+ */
void *tss_get(tss_t key);
/** Set the value for a thread-specific storage.
-* @param key The thread-specific storage identifier.
-* @param val The value of the thread-specific storage to set for the current
-* thread.
-* @return @ref thrd_success on success, or @ref thrd_error if the request could
-* not be honored.
-*/
+ * @param key The thread-specific storage identifier.
+ * @param val The value of the thread-specific storage to set for the current
+ * thread.
+ * @return @ref thrd_success on success, or @ref thrd_error if the request could
+ * not be honored.
+ */
int tss_set(tss_t key, void *val);
-
#endif /* _TINYTHREAD_H_ */
-
#include "vkvg.h"
-#define TRY_LOAD_DEVICE_EXT(ext) { \
-if (vkh_phyinfo_try_get_extension_properties(pi, #ext, NULL)) \
- enabledExts[enabledExtsCount++] = #ext; \
-}
+#define TRY_LOAD_DEVICE_EXT(ext) \
+ { \
+ if (vkh_phyinfo_try_get_extension_properties(pi, #ext, NULL)) \
+ enabledExts[enabledExtsCount++] = #ext; \
+ }
static void glfw_error_callback(int error, const char *description) {
- fprintf(stderr, "vkengine: GLFW error %d: %s\n", error, description);
+ fprintf(stderr, "vkengine: GLFW error %d: %s\n", error, description);
}
-VkSampleCountFlagBits getMaxUsableSampleCount(VkSampleCountFlags counts)
-{
- if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; }
- if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; }
- if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; }
- if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; }
- if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; }
- if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }
- return VK_SAMPLE_COUNT_1_BIT;
+VkSampleCountFlagBits getMaxUsableSampleCount(VkSampleCountFlags counts) {
+ if (counts & VK_SAMPLE_COUNT_64_BIT) {
+ return VK_SAMPLE_COUNT_64_BIT;
+ }
+ if (counts & VK_SAMPLE_COUNT_32_BIT) {
+ return VK_SAMPLE_COUNT_32_BIT;
+ }
+ if (counts & VK_SAMPLE_COUNT_16_BIT) {
+ return VK_SAMPLE_COUNT_16_BIT;
+ }
+ if (counts & VK_SAMPLE_COUNT_8_BIT) {
+ return VK_SAMPLE_COUNT_8_BIT;
+ }
+ if (counts & VK_SAMPLE_COUNT_4_BIT) {
+ return VK_SAMPLE_COUNT_4_BIT;
+ }
+ if (counts & VK_SAMPLE_COUNT_2_BIT) {
+ return VK_SAMPLE_COUNT_2_BIT;
+ }
+ return VK_SAMPLE_COUNT_1_BIT;
}
-void vkengine_dump_Infos (VkEngine e){
- printf("max samples = %d\n", getMaxUsableSampleCount(e->gpu_props.limits.framebufferColorSampleCounts));
- printf("max tex2d size = %d\n", e->gpu_props.limits.maxImageDimension2D);
- printf("max tex array layers = %d\n", e->gpu_props.limits.maxImageArrayLayers);
- printf("max mem alloc count = %d\n", e->gpu_props.limits.maxMemoryAllocationCount);
-
- for (uint32_t i = 0; i < e->memory_properties.memoryHeapCount; i++) {
- printf("Mem Heap %d\n", i);
- printf("\tflags= %d\n", e->memory_properties.memoryHeaps[i].flags);
- printf("\tsize = %lu Mo\n", (unsigned long)e->memory_properties.memoryHeaps[i].size/ (uint32_t)(1024*1024));
- }
- for (uint32_t i = 0; i < e->memory_properties.memoryTypeCount; i++) {
- printf("Mem type %d\n", i);
- printf("\theap %d: ", e->memory_properties.memoryTypes[i].heapIndex);
- if (e->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
- printf("VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT|");
- if (e->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
- printf("VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|");
- if (e->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
- printf("VK_MEMORY_PROPERTY_HOST_COHERENT_BIT|");
- if (e->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
- printf("VK_MEMORY_PROPERTY_HOST_CACHED_BIT|");
- if (e->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
- printf("VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT|");
- printf("\n");
- }
+void vkengine_dump_Infos(VkEngine e) {
+ printf("max samples = %d\n", getMaxUsableSampleCount(e->gpu_props.limits.framebufferColorSampleCounts));
+ printf("max tex2d size = %d\n", e->gpu_props.limits.maxImageDimension2D);
+ printf("max tex array layers = %d\n", e->gpu_props.limits.maxImageArrayLayers);
+ printf("max mem alloc count = %d\n", e->gpu_props.limits.maxMemoryAllocationCount);
+
+ for (uint32_t i = 0; i < e->memory_properties.memoryHeapCount; i++) {
+ printf("Mem Heap %d\n", i);
+ printf("\tflags= %d\n", e->memory_properties.memoryHeaps[i].flags);
+ printf("\tsize = %lu Mo\n", (unsigned long)e->memory_properties.memoryHeaps[i].size / (uint32_t)(1024 * 1024));
+ }
+ for (uint32_t i = 0; i < e->memory_properties.memoryTypeCount; i++) {
+ printf("Mem type %d\n", i);
+ printf("\theap %d: ", e->memory_properties.memoryTypes[i].heapIndex);
+ if (e->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
+ printf("VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT|");
+ if (e->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+ printf("VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|");
+ if (e->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
+ printf("VK_MEMORY_PROPERTY_HOST_COHERENT_BIT|");
+ if (e->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
+ printf("VK_MEMORY_PROPERTY_HOST_CACHED_BIT|");
+ if (e->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
+ printf("VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT|");
+ printf("\n");
+ }
}
+void vkengine_dump_available_layers() {
+ uint32_t layerCount;
+ vkEnumerateInstanceLayerProperties(&layerCount, NULL);
+ VkLayerProperties *availableLayers = (VkLayerProperties *)malloc(layerCount * sizeof(VkLayerProperties));
+ vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);
-void vkengine_dump_available_layers () {
- uint32_t layerCount;
- vkEnumerateInstanceLayerProperties(&layerCount, NULL);
-
- VkLayerProperties* availableLayers = (VkLayerProperties*)malloc(layerCount*sizeof(VkLayerProperties));
- vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);
-
- printf("Available Layers:\n");
- printf("-----------------\n");
- for (uint32_t i=0; i<layerCount; i++) {
- printf ("\t - %s\n", availableLayers[i].layerName);
- }
- printf("-----------------\n\n");
- free (availableLayers);
+ printf("Available Layers:\n");
+ printf("-----------------\n");
+ for (uint32_t i = 0; i < layerCount; i++) {
+ printf("\t - %s\n", availableLayers[i].layerName);
+ }
+ printf("-----------------\n\n");
+ free(availableLayers);
}
-bool vkengine_try_get_phyinfo (VkhPhyInfo* phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo* phy) {
- for (uint32_t i=0; i<phyCount; i++){
- if (phys[i]->properties.deviceType == gpuType) {
- *phy = phys[i];
- return true;
- }
- }
- return false;
+bool vkengine_try_get_phyinfo(VkhPhyInfo *phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo *phy) {
+ for (uint32_t i = 0; i < phyCount; i++) {
+ if (phys[i]->properties.deviceType == gpuType) {
+ *phy = phys[i];
+ return true;
+ }
+ }
+ return false;
}
-bool instance_extension_supported (VkExtensionProperties* instanceExtProps, uint32_t extCount, const char* instanceName) {
- for (uint32_t i=0; i<extCount; i++) {
- if (!strcmp(instanceExtProps[i].extensionName, instanceName))
- return true;
- }
- return false;
+bool instance_extension_supported(VkExtensionProperties *instanceExtProps, uint32_t extCount,
+ const char *instanceName) {
+ for (uint32_t i = 0; i < extCount; i++) {
+ if (!strcmp(instanceExtProps[i].extensionName, instanceName))
+ return true;
+ }
+ return false;
}
-vk_engine_t* vkengine_create (VkPhysicalDeviceType preferedGPU, VkPresentModeKHR presentMode, uint32_t width, uint32_t height) {
- glfwSetErrorCallback(glfw_error_callback);
+vk_engine_t *vkengine_create(VkPhysicalDeviceType preferedGPU, VkPresentModeKHR presentMode, uint32_t width,
+ uint32_t height) {
+ glfwSetErrorCallback(glfw_error_callback);
- if (!glfwInit()) {
- perror ("glfwInit failed");
- exit(-1);
- }
+ if (!glfwInit()) {
+ perror("glfwInit failed");
+ exit(-1);
+ }
- if (!glfwVulkanSupported()) {
- perror ("glfwVulkanSupported return false.");
- exit(-1);
- }
+ if (!glfwVulkanSupported()) {
+ perror("glfwVulkanSupported return false.");
+ exit(-1);
+ }
- const char* enabledLayers[10];
- const char* enabledExts [10];
- uint32_t enabledExtsCount = 0, enabledLayersCount = 0, phyCount = 0;
+ const char *enabledLayers[10];
+ const char *enabledExts[10];
+ uint32_t enabledExtsCount = 0, enabledLayersCount = 0, phyCount = 0;
- vkh_layers_check_init();
+ vkh_layers_check_init();
#ifdef VKVG_USE_VALIDATION
- if (vkh_layer_is_present("VK_LAYER_KHRONOS_validation"))
- enabledLayers[enabledLayersCount++] = "VK_LAYER_KHRONOS_validation";
+ if (vkh_layer_is_present("VK_LAYER_KHRONOS_validation"))
+ enabledLayers[enabledLayersCount++] = "VK_LAYER_KHRONOS_validation";
#endif
#ifdef VKVG_USE_MESA_OVERLAY
- if (vkh_layer_is_present("VK_LAYER_MESA_overlay"))
- enabledLayers[enabledLayersCount++] = "VK_LAYER_MESA_overlay";
+ if (vkh_layer_is_present("VK_LAYER_MESA_overlay"))
+ enabledLayers[enabledLayersCount++] = "VK_LAYER_MESA_overlay";
#endif
#ifdef VKVG_USE_RENDERDOC
- if (vkh_layer_is_present("VK_LAYER_RENDERDOC_Capture"))
- enabledLayers[enabledLayersCount++] = "VK_LAYER_RENDERDOC_Capture";
+ if (vkh_layer_is_present("VK_LAYER_RENDERDOC_Capture"))
+ enabledLayers[enabledLayersCount++] = "VK_LAYER_RENDERDOC_Capture";
#endif
- vkh_layers_check_release();
+ vkh_layers_check_release();
- uint32_t glfwReqExtsCount = 0;
- const char** gflwExts = glfwGetRequiredInstanceExtensions (&glfwReqExtsCount);
+ uint32_t glfwReqExtsCount = 0;
+ const char **gflwExts = glfwGetRequiredInstanceExtensions(&glfwReqExtsCount);
- vkvg_get_required_instance_extensions (enabledExts, &enabledExtsCount);
+ vkvg_get_required_instance_extensions(enabledExts, &enabledExtsCount);
- for (uint32_t i=0;i<glfwReqExtsCount;i++)
- enabledExts[i+enabledExtsCount] = gflwExts[i];
+ for (uint32_t i = 0; i < glfwReqExtsCount; i++)
+ enabledExts[i + enabledExtsCount] = gflwExts[i];
- enabledExtsCount += glfwReqExtsCount;
+ enabledExtsCount += glfwReqExtsCount;
- vk_engine_t* e = (vk_engine_t*)calloc(1,sizeof(vk_engine_t));
+ vk_engine_t *e = (vk_engine_t *)calloc(1, sizeof(vk_engine_t));
#ifdef VK_VERSION_1_2
- e->app = vkh_app_create(1, 2, "vkvg", enabledLayersCount, enabledLayers, enabledExtsCount, enabledExts);
+ e->app = vkh_app_create(1, 2, "vkvg", enabledLayersCount, enabledLayers, enabledExtsCount, enabledExts);
#else
- e->app = vkh_app_create(1, 1, "vkvg", enabledLayersCount, enabledLayers, enabledExtsCount, enabledExts);
+ e->app = vkh_app_create(1, 1, "vkvg", enabledLayersCount, enabledLayers, enabledExtsCount, enabledExts);
#endif
-
-#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
- vkh_app_enable_debug_messenger(e->app
- , VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
- //| VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
- //| VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
- , VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
- | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
- //| VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
- //| VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
- , NULL);
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_app_enable_debug_messenger(e->app,
+ VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
+ //| VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
+ //| VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
+ ,
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
+ //| VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
+ //| VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
+ ,
+ NULL);
#endif
- glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
- glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
- glfwWindowHint(GLFW_FLOATING, GLFW_FALSE);
- glfwWindowHint(GLFW_DECORATED, GLFW_TRUE);
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+ glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
+ glfwWindowHint(GLFW_FLOATING, GLFW_FALSE);
+ glfwWindowHint(GLFW_DECORATED, GLFW_TRUE);
- e->window = glfwCreateWindow ((int)width, (int)height, "Window Title", NULL, NULL);
+ e->window = glfwCreateWindow((int)width, (int)height, "Window Title", NULL, NULL);
- VkSurfaceKHR surf;
- VK_CHECK_RESULT (glfwCreateWindowSurface(e->app->inst, e->window, NULL, &surf))
+ VkSurfaceKHR surf;
+ VK_CHECK_RESULT(glfwCreateWindowSurface(e->app->inst, e->window, NULL, &surf))
- VkhPhyInfo* phys = vkh_app_get_phyinfos (e->app, &phyCount, surf);
+ VkhPhyInfo *phys = vkh_app_get_phyinfos(e->app, &phyCount, surf);
- VkhPhyInfo pi = 0;
- if (!vkengine_try_get_phyinfo(phys, phyCount, preferedGPU, &pi)
- && !vkengine_try_get_phyinfo(phys, phyCount, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, &pi)
- && !vkengine_try_get_phyinfo(phys, phyCount, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, &pi))
- pi = phys[0];
- assert(pi && "No vulkan physical device found.");
+ VkhPhyInfo pi = 0;
+ if (!vkengine_try_get_phyinfo(phys, phyCount, preferedGPU, &pi) &&
+ !vkengine_try_get_phyinfo(phys, phyCount, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, &pi) &&
+ !vkengine_try_get_phyinfo(phys, phyCount, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, &pi))
+ pi = phys[0];
+ assert(pi && "No vulkan physical device found.");
- e->memory_properties = pi->memProps;
- e->gpu_props = pi->properties;
+ e->memory_properties = pi->memProps;
+ e->gpu_props = pi->properties;
- uint32_t qCount = 0;
- float qPriorities[] = {0.0};
+ uint32_t qCount = 0;
+ float qPriorities[] = {0.0};
- VkDeviceQueueCreateInfo pQueueInfos[] = { {0},{0},{0} };
- if (vkh_phyinfo_create_presentable_queues (pi, 1, qPriorities, &pQueueInfos[qCount]))
- qCount++;
- /*if (vkh_phyinfo_create_compute_queues (pi, 1, qPriorities, &pQueueInfos[qCount]))
- qCount++;
- if (vkh_phyinfo_create_transfer_queues (pi, 1, qPriorities, &pQueueInfos[qCount]))
- qCount++;*/
+ VkDeviceQueueCreateInfo pQueueInfos[] = {{0}, {0}, {0}};
+ if (vkh_phyinfo_create_presentable_queues(pi, 1, qPriorities, &pQueueInfos[qCount]))
+ qCount++;
+ /*if (vkh_phyinfo_create_compute_queues (pi, 1, qPriorities, &pQueueInfos[qCount]))
+ qCount++;
+ if (vkh_phyinfo_create_transfer_queues (pi, 1, qPriorities, &pQueueInfos[qCount]))
+ qCount++;*/
- enabledExtsCount=0;
+ enabledExtsCount = 0;
- if (vkvg_get_required_device_extensions (pi->phy, enabledExts, &enabledExtsCount) != VKVG_STATUS_SUCCESS) {
- perror ("vkvg_get_required_device_extensions failed, enable log for details.\n");
- exit(-1);
- }
- TRY_LOAD_DEVICE_EXT (VK_KHR_swapchain)
+ if (vkvg_get_required_device_extensions(pi->phy, enabledExts, &enabledExtsCount) != VKVG_STATUS_SUCCESS) {
+ perror("vkvg_get_required_device_extensions failed, enable log for details.\n");
+ exit(-1);
+ }
+ TRY_LOAD_DEVICE_EXT(VK_KHR_swapchain)
- VkPhysicalDeviceFeatures enabledFeatures = {0};
- const void* pNext = vkvg_get_device_requirements (&enabledFeatures);
+ VkPhysicalDeviceFeatures enabledFeatures = {0};
+ const void *pNext = vkvg_get_device_requirements(&enabledFeatures);
- VkDeviceCreateInfo device_info = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- .queueCreateInfoCount = qCount,
- .pQueueCreateInfos = (VkDeviceQueueCreateInfo*)&pQueueInfos,
- .enabledExtensionCount = enabledExtsCount,
- .ppEnabledExtensionNames = enabledExts,
- .pEnabledFeatures = &enabledFeatures,
- .pNext = pNext};
+ VkDeviceCreateInfo device_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ .queueCreateInfoCount = qCount,
+ .pQueueCreateInfos = (VkDeviceQueueCreateInfo *)&pQueueInfos,
+ .enabledExtensionCount = enabledExtsCount,
+ .ppEnabledExtensionNames = enabledExts,
+ .pEnabledFeatures = &enabledFeatures,
+ .pNext = pNext};
- e->dev = vkh_device_create(e->app, pi, &device_info);
+ e->dev = vkh_device_create(e->app, pi, &device_info);
- e->renderer = vkh_presenter_create
- (e->dev, (uint32_t) pi->pQueue, surf, width, height, VK_FORMAT_B8G8R8A8_UNORM, presentMode);
+ e->renderer =
+ vkh_presenter_create(e->dev, (uint32_t)pi->pQueue, surf, width, height, VK_FORMAT_B8G8R8A8_UNORM, presentMode);
- vkh_app_free_phyinfos (phyCount, phys);
+ vkh_app_free_phyinfos(phyCount, phys);
- return e;
+ return e;
}
-void vkengine_destroy (VkEngine e) {
- //vkDeviceWaitIdle(e->dev->dev);
+void vkengine_destroy(VkEngine e) {
+ // vkDeviceWaitIdle(e->dev->dev);
- VkSurfaceKHR surf = e->renderer->surface;
+ VkSurfaceKHR surf = e->renderer->surface;
- vkh_presenter_destroy (e->renderer);
- vkDestroySurfaceKHR (e->app->inst, surf, NULL);
+ vkh_presenter_destroy(e->renderer);
+ vkDestroySurfaceKHR(e->app->inst, surf, NULL);
- vkh_device_destroy (e->dev);
+ vkh_device_destroy(e->dev);
- glfwDestroyWindow (e->window);
- vkh_app_destroy (e->app);
+ glfwDestroyWindow(e->window);
+ vkh_app_destroy(e->app);
- glfwTerminate ();
+ glfwTerminate();
- free(e);
-}
-void vkengine_close (VkEngine e) {
- glfwSetWindowShouldClose(e->window, GLFW_TRUE);
-}
-void vkengine_blitter_run (VkEngine e, VkImage img, uint32_t width, uint32_t height) {
- VkhPresenter p = e->renderer;
- vkh_presenter_build_blit_cmd (p, img, width, height);
-
- while (!vkengine_should_close (e)) {
- glfwPollEvents();
- if (!vkh_presenter_draw (p))
- vkh_presenter_build_blit_cmd (p, img, width, height);
- }
-}
-bool vkengine_should_close (VkEngine e) {
- return glfwWindowShouldClose (e->window);
-}
-void vkengine_set_title (VkEngine e, const char* title) {
- glfwSetWindowTitle(e->window, title);
-}
-VkInstance vkengine_get_instance (VkEngine e){
- return e->dev->instance;
-}
-VkDevice vkengine_get_device (VkEngine e){
- return e->dev->dev;
-}
-VkPhysicalDevice vkengine_get_physical_device (VkEngine e){
- return e->dev->phy;
-}
-VkQueue vkengine_get_queue (VkEngine e){
- return e->renderer->queue;
-}
-uint32_t vkengine_get_queue_fam_idx (VkEngine e){
- return e->renderer->qFam;
-}
-void vkengine_wait_idle (VkEngine e) {
- vkDeviceWaitIdle(e->dev->dev);
-}
-
-void vkengine_set_key_callback (VkEngine e, GLFWkeyfun key_callback){
- glfwSetKeyCallback (e->window, key_callback);
-}
-void vkengine_set_mouse_but_callback (VkEngine e, GLFWmousebuttonfun onMouseBut){
- glfwSetMouseButtonCallback(e->window, onMouseBut);
+ free(e);
}
-void vkengine_set_cursor_pos_callback (VkEngine e, GLFWcursorposfun onMouseMove){
- glfwSetCursorPosCallback(e->window, onMouseMove);
+void vkengine_close(VkEngine e) { glfwSetWindowShouldClose(e->window, GLFW_TRUE); }
+void vkengine_blitter_run(VkEngine e, VkImage img, uint32_t width, uint32_t height) {
+ VkhPresenter p = e->renderer;
+ vkh_presenter_build_blit_cmd(p, img, width, height);
+
+ while (!vkengine_should_close(e)) {
+ glfwPollEvents();
+ if (!vkh_presenter_draw(p))
+ vkh_presenter_build_blit_cmd(p, img, width, height);
+ }
}
-void vkengine_set_scroll_callback (VkEngine e, GLFWscrollfun onScroll){
- glfwSetScrollCallback(e->window, onScroll);
+bool vkengine_should_close(VkEngine e) { return glfwWindowShouldClose(e->window); }
+void vkengine_set_title(VkEngine e, const char *title) { glfwSetWindowTitle(e->window, title); }
+VkInstance vkengine_get_instance(VkEngine e) { return e->dev->instance; }
+VkDevice vkengine_get_device(VkEngine e) { return e->dev->dev; }
+VkPhysicalDevice vkengine_get_physical_device(VkEngine e) { return e->dev->phy; }
+VkQueue vkengine_get_queue(VkEngine e) { return e->renderer->queue; }
+uint32_t vkengine_get_queue_fam_idx(VkEngine e) { return e->renderer->qFam; }
+void vkengine_wait_idle(VkEngine e) { vkDeviceWaitIdle(e->dev->dev); }
+
+void vkengine_set_key_callback(VkEngine e, GLFWkeyfun key_callback) { glfwSetKeyCallback(e->window, key_callback); }
+void vkengine_set_mouse_but_callback(VkEngine e, GLFWmousebuttonfun onMouseBut) {
+ glfwSetMouseButtonCallback(e->window, onMouseBut);
}
-void vkengine_set_char_callback (VkEngine e, GLFWcharfun onChar){
- glfwSetCharCallback(e->window, onChar);
+void vkengine_set_cursor_pos_callback(VkEngine e, GLFWcursorposfun onMouseMove) {
+ glfwSetCursorPosCallback(e->window, onMouseMove);
}
+void vkengine_set_scroll_callback(VkEngine e, GLFWscrollfun onScroll) { glfwSetScrollCallback(e->window, onScroll); }
+void vkengine_set_char_callback(VkEngine e, GLFWcharfun onChar) { glfwSetCharCallback(e->window, onChar); }
#define FENCE_TIMEOUT 100000000
-typedef struct _vk_engine_t* VkEngine;
+typedef struct _vk_engine_t *VkEngine;
typedef struct _vk_engine_t {
- VkhApp app;
- VkPhysicalDeviceMemoryProperties memory_properties;
- VkPhysicalDeviceProperties gpu_props;
- VkhDevice dev;
- GLFWwindow* window;
- VkhPresenter renderer;
-}vk_engine_t;
+ VkhApp app;
+ VkPhysicalDeviceMemoryProperties memory_properties;
+ VkPhysicalDeviceProperties gpu_props;
+ VkhDevice dev;
+ GLFWwindow *window;
+ VkhPresenter renderer;
+} vk_engine_t;
-vk_engine_t* vkengine_create (VkPhysicalDeviceType preferedGPU, VkPresentModeKHR presentMode, uint32_t width, uint32_t height);
-void vkengine_dump_available_layers ();
-bool vkengine_try_get_phyinfo (VkhPhyInfo* phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo* phy);
-void vkengine_destroy (VkEngine e);
-bool vkengine_should_close (VkEngine e);
-void vkengine_close (VkEngine e);
-void vkengine_dump_Infos (VkEngine e);
-void vkengine_set_title (VkEngine e, const char* title);
-VkInstance vkengine_get_instance (VkEngine e);
-VkDevice vkengine_get_device (VkEngine e);
-VkPhysicalDevice vkengine_get_physical_device(VkEngine e);
-VkQueue vkengine_get_queue (VkEngine e);
-uint32_t vkengine_get_queue_fam_idx (VkEngine e);
+vk_engine_t *vkengine_create(VkPhysicalDeviceType preferedGPU, VkPresentModeKHR presentMode, uint32_t width,
+ uint32_t height);
+void vkengine_dump_available_layers();
+bool vkengine_try_get_phyinfo(VkhPhyInfo *phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo *phy);
+void vkengine_destroy(VkEngine e);
+bool vkengine_should_close(VkEngine e);
+void vkengine_close(VkEngine e);
+void vkengine_dump_Infos(VkEngine e);
+void vkengine_set_title(VkEngine e, const char *title);
+VkInstance vkengine_get_instance(VkEngine e);
+VkDevice vkengine_get_device(VkEngine e);
+VkPhysicalDevice vkengine_get_physical_device(VkEngine e);
+VkQueue vkengine_get_queue(VkEngine e);
+uint32_t vkengine_get_queue_fam_idx(VkEngine e);
-void vkengine_get_queues_properties (vk_engine_t* e, VkQueueFamilyProperties** qFamProps, uint32_t* count);
+void vkengine_get_queues_properties(vk_engine_t *e, VkQueueFamilyProperties **qFamProps, uint32_t *count);
-void vkengine_set_key_callback (VkEngine e, GLFWkeyfun key_callback);
-void vkengine_set_mouse_but_callback (VkEngine e, GLFWmousebuttonfun onMouseBut);
-void vkengine_set_cursor_pos_callback (VkEngine e, GLFWcursorposfun onMouseMove);
-void vkengine_set_scroll_callback (VkEngine e, GLFWscrollfun onScroll);
-void vkengine_set_char_callback (VkEngine e, GLFWcharfun onChar);
+void vkengine_set_key_callback(VkEngine e, GLFWkeyfun key_callback);
+void vkengine_set_mouse_but_callback(VkEngine e, GLFWmousebuttonfun onMouseBut);
+void vkengine_set_cursor_pos_callback(VkEngine e, GLFWcursorposfun onMouseMove);
+void vkengine_set_scroll_callback(VkEngine e, GLFWscrollfun onScroll);
+void vkengine_set_char_callback(VkEngine e, GLFWcharfun onChar);
-void vkengine_wait_idle (VkEngine e);
+void vkengine_wait_idle(VkEngine e);
#endif
#include "test.h"
-void compositing(){
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
+void compositing() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
- vkvg_set_source_rgba(ctx, 1,0,0,0.5f);
- vkvg_rectangle(ctx,100,100,200,200);
- vkvg_fill(ctx);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.5f);
+ vkvg_rectangle(ctx, 100, 100, 200, 200);
+ vkvg_fill(ctx);
- vkvg_set_source_rgba(ctx, 0,0,1,0.5f);
- vkvg_rectangle(ctx,200,200,200,200);
- vkvg_fill(ctx);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 0.5f);
+ vkvg_rectangle(ctx, 200, 200, 200, 200);
+ vkvg_fill(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
-void opacity(){
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
+void opacity() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
- vkvg_set_source_rgba(ctx, 1,0,0,1.0f);
- vkvg_rectangle(ctx,100,100,200,200);
- vkvg_fill(ctx);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1.0f);
+ vkvg_rectangle(ctx, 100, 100, 200, 200);
+ vkvg_fill(ctx);
- vkvg_set_opacity(ctx,0.5f);
+ vkvg_set_opacity(ctx, 0.5f);
- vkvg_set_source_rgba(ctx, 0,0,1,1.0f);
- vkvg_rectangle(ctx,200,200,200,200);
- vkvg_fill(ctx);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 1.0f);
+ vkvg_rectangle(ctx, 200, 200, 200, 200);
+ vkvg_fill(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
-
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (compositing, argc, argv);
- PERFORM_TEST (opacity, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(compositing, argc, argv);
+ PERFORM_TEST(opacity, argc, argv);
+ return 0;
}
#include "test.h"
-void create_destroy_multi(){
- VkvgContext* ctxs = (VkvgContext*)malloc(sizeof(VkvgContext)*test_size);
- for (uint32_t i = 0; i < test_size; i++)
- ctxs[i] = vkvg_create(surf);
- for (uint32_t i = 0; i < test_size; i++)
- vkvg_destroy(ctxs[i]);
- free(ctxs);
+void create_destroy_multi() {
+ VkvgContext *ctxs = (VkvgContext *)malloc(sizeof(VkvgContext) * test_size);
+ for (uint32_t i = 0; i < test_size; i++)
+ ctxs[i] = vkvg_create(surf);
+ for (uint32_t i = 0; i < test_size; i++)
+ vkvg_destroy(ctxs[i]);
+ free(ctxs);
}
-void create_destroy_single(){
- VkvgContext ctx = vkvg_create(surf);
- vkvg_destroy(ctx);
+void create_destroy_single() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- PERFORM_TEST (create_destroy_multi, argc, argv);
- no_test_size = true;
- PERFORM_TEST (create_destroy_single, argc, argv);
- return 0;
+ PERFORM_TEST(create_destroy_multi, argc, argv);
+ no_test_size = true;
+ PERFORM_TEST(create_destroy_single, argc, argv);
+ return 0;
}
//"M80 170 C100 170 160 170 180 170 lZ"
void test3() {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear (ctx);
- vkvg_set_line_width(ctx, 20);
- vkvg_set_source_rgb (ctx,1,0,0);
- vkvg_move_to (ctx,80,170);
- vkvg_curve_to (ctx, 100,170,160,171,180,170);
- //vkvg_rel_line_to (ctx, -30,100);
- vkvg_close_path (ctx);
- vkvg_stroke (ctx);
- vkvg_destroy (ctx);
-
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+ vkvg_set_line_width(ctx, 20);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_move_to(ctx, 80, 170);
+ vkvg_curve_to(ctx, 100, 170, 160, 171, 180, 170);
+ // vkvg_rel_line_to (ctx, -30,100);
+ vkvg_close_path(ctx);
+ vkvg_stroke(ctx);
+ vkvg_destroy(ctx);
}
-void test(){
- VkvgContext ctx = vkvg_create(surf);
-
- vkvg_set_line_width(ctx, 20);
-
- vkvg_scale(ctx,2,2);
- vkvg_set_line_join(ctx, VKVG_LINE_JOIN_BEVEL);
-
- //vkvg_arc (ctx, 200, 500, 100, 0, M_PI);
-
- vkvg_set_source_rgb (ctx, 0.5f,0,0);
-
-
- /*vkvg_move_to(ctx,100,100);
- vkvg_line_to(ctx,300,100);
- vkvg_line_to(ctx,500,300);
- vkvg_line_to(ctx,300,500);
- //vkvg_arc (ctx, 200, 500, 100, 0, M_PI);
- vkvg_line_to(ctx,300,700);
- vkvg_line_to(ctx,100,500);*/
-
- /*vkvg_arc(ctx, 300, 300, 100, 0, M_PI);
- vkvg_line_to(ctx,100,200);
- vkvg_line_to(ctx,200,100);
- vkvg_arc(ctx, 250, 100, 50, M_PI, M_PI * 1.5f);
- vkvg_line_to(ctx,350,50);
- vkvg_arc(ctx, 350, 100, 50, M_PI*1.5f, M_PI * 2.0f);
-
- vkvg_stroke(ctx);
- vkvg_translate(ctx,400,30);
-
- */
- //vkvg_set_fill_rule(ctx,VKVG_FILL_RULE_EVEN_ODD);
- vkvg_translate(ctx,200,30);
- vkvg_arc(ctx, 200, 200, 20, 0, M_PIF*2);
- //vkvg_stroke(ctx);
-
- vkvg_set_source_rgba (ctx, 0.5f,0.0f,1.0f,0.5f);
- vkvg_move_to(ctx,100,100);
- vkvg_line_to(ctx,200,100);
- //vkvg_move_to(ctx,200,100);
- vkvg_curve_to(ctx,250,100,300,150,300,200);
- vkvg_line_to(ctx,300,300);
- vkvg_curve_to(ctx,300,350,250,400,200,400);
- vkvg_line_to(ctx,100,400);
- vkvg_curve_to(ctx,50,400,10,350,10,300);
- vkvg_line_to(ctx,10,200);
- vkvg_curve_to(ctx,10,150,50,100,100,100);
- //vkvg_close_path(ctx);
- vkvg_fill_preserve(ctx);
- vkvg_set_source_rgba (ctx, 0.1f,0.3f,0.7f,0.5f);
- vkvg_stroke(ctx);
-
-
- vkvg_destroy(ctx);
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
+
+ vkvg_set_line_width(ctx, 20);
+
+ vkvg_scale(ctx, 2, 2);
+ vkvg_set_line_join(ctx, VKVG_LINE_JOIN_BEVEL);
+
+ // vkvg_arc (ctx, 200, 500, 100, 0, M_PI);
+
+ vkvg_set_source_rgb(ctx, 0.5f, 0, 0);
+
+ /*vkvg_move_to(ctx,100,100);
+ vkvg_line_to(ctx,300,100);
+ vkvg_line_to(ctx,500,300);
+ vkvg_line_to(ctx,300,500);
+ //vkvg_arc (ctx, 200, 500, 100, 0, M_PI);
+ vkvg_line_to(ctx,300,700);
+ vkvg_line_to(ctx,100,500);*/
+
+ /*vkvg_arc(ctx, 300, 300, 100, 0, M_PI);
+ vkvg_line_to(ctx,100,200);
+ vkvg_line_to(ctx,200,100);
+ vkvg_arc(ctx, 250, 100, 50, M_PI, M_PI * 1.5f);
+ vkvg_line_to(ctx,350,50);
+ vkvg_arc(ctx, 350, 100, 50, M_PI*1.5f, M_PI * 2.0f);
+
+ vkvg_stroke(ctx);
+ vkvg_translate(ctx,400,30);
+
+ */
+ // vkvg_set_fill_rule(ctx,VKVG_FILL_RULE_EVEN_ODD);
+ vkvg_translate(ctx, 200, 30);
+ vkvg_arc(ctx, 200, 200, 20, 0, M_PIF * 2);
+ // vkvg_stroke(ctx);
+
+ vkvg_set_source_rgba(ctx, 0.5f, 0.0f, 1.0f, 0.5f);
+ vkvg_move_to(ctx, 100, 100);
+ vkvg_line_to(ctx, 200, 100);
+ // vkvg_move_to(ctx,200,100);
+ vkvg_curve_to(ctx, 250, 100, 300, 150, 300, 200);
+ vkvg_line_to(ctx, 300, 300);
+ vkvg_curve_to(ctx, 300, 350, 250, 400, 200, 400);
+ vkvg_line_to(ctx, 100, 400);
+ vkvg_curve_to(ctx, 50, 400, 10, 350, 10, 300);
+ vkvg_line_to(ctx, 10, 200);
+ vkvg_curve_to(ctx, 10, 150, 50, 100, 100, 100);
+ // vkvg_close_path(ctx);
+ vkvg_fill_preserve(ctx);
+ vkvg_set_source_rgba(ctx, 0.1f, 0.3f, 0.7f, 0.5f);
+ vkvg_stroke(ctx);
+
+ vkvg_destroy(ctx);
}
void curved_rect() {
- VkvgContext ctx = vkvg_create(surf);
-
- float x = 50, y = 50, width = 150, height = 140, radius = 30;
-
- vkvg_scale(ctx, 2, 2);
- //vkvg_rotate(ctx,0.5f);
-
- vkvg_set_line_width(ctx, 15);
- vkvg_set_source_rgba(ctx, 0, 0.5f, 0.4f, 1);
-
- if ((radius > height / 2) || (radius > width / 2))
- radius = MIN(height / 2, width / 2);
-
- vkvg_move_to(ctx, x, y + radius);
- vkvg_arc(ctx, x + radius, y + radius, radius, M_PIF, (float)-M_PI_2);
- vkvg_line_to(ctx, x + width - radius, y);
- vkvg_arc(ctx, x + width - radius, y + radius, radius, (float)-M_PI_2, 0);
- vkvg_line_to(ctx, x + width, y + height - radius);
- vkvg_arc(ctx, x + width - radius, y + height - radius, radius, 0, (float)M_PI_2);
- vkvg_line_to(ctx, x + radius, y + height);
- vkvg_arc(ctx, x + radius, y + height - radius, radius, (float)M_PI_2, M_PIF);
- vkvg_line_to(ctx, x, y + radius);
- vkvg_close_path(ctx);
- vkvg_fill_preserve(ctx);
- vkvg_set_source_rgba(ctx, 0.5f, 0, 0, 0.5f);
- vkvg_stroke(ctx);
-
- vkvg_destroy(ctx);
+ VkvgContext ctx = vkvg_create(surf);
+
+ float x = 50, y = 50, width = 150, height = 140, radius = 30;
+
+ vkvg_scale(ctx, 2, 2);
+ // vkvg_rotate(ctx,0.5f);
+
+ vkvg_set_line_width(ctx, 15);
+ vkvg_set_source_rgba(ctx, 0, 0.5f, 0.4f, 1);
+
+ if ((radius > height / 2) || (radius > width / 2))
+ radius = MIN(height / 2, width / 2);
+
+ vkvg_move_to(ctx, x, y + radius);
+ vkvg_arc(ctx, x + radius, y + radius, radius, M_PIF, (float)-M_PI_2);
+ vkvg_line_to(ctx, x + width - radius, y);
+ vkvg_arc(ctx, x + width - radius, y + radius, radius, (float)-M_PI_2, 0);
+ vkvg_line_to(ctx, x + width, y + height - radius);
+ vkvg_arc(ctx, x + width - radius, y + height - radius, radius, 0, (float)M_PI_2);
+ vkvg_line_to(ctx, x + radius, y + height);
+ vkvg_arc(ctx, x + radius, y + height - radius, radius, (float)M_PI_2, M_PIF);
+ vkvg_line_to(ctx, x, y + radius);
+ vkvg_close_path(ctx);
+ vkvg_fill_preserve(ctx);
+ vkvg_set_source_rgba(ctx, 0.5f, 0, 0, 0.5f);
+ vkvg_stroke(ctx);
+
+ vkvg_destroy(ctx);
}
void test2() {
- VkvgContext ctx = vkvg_create(surf);
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_move_to(ctx, 100, 400);
- vkvg_curve_to(ctx, 100, 100, 600, 700, 600, 400);
- vkvg_curve_to(ctx, 1000, 100, 100, 800, 1000, 800);
- vkvg_curve_to(ctx, 1000, 500, 700, 500, 700, 100);
- vkvg_close_path(ctx);
+ vkvg_move_to(ctx, 100, 400);
+ vkvg_curve_to(ctx, 100, 100, 600, 700, 600, 400);
+ vkvg_curve_to(ctx, 1000, 100, 100, 800, 1000, 800);
+ vkvg_curve_to(ctx, 1000, 500, 700, 500, 700, 100);
+ vkvg_close_path(ctx);
- //vkvg_set_source_rgba (ctx, 0.5,0.0,1.0,0.5);
- //vkvg_fill_preserve(ctx);
+ // vkvg_set_source_rgba (ctx, 0.5,0.0,1.0,0.5);
+ // vkvg_fill_preserve(ctx);
- vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
- vkvg_set_line_width(ctx, 40);
- vkvg_stroke(ctx);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_set_line_width(ctx, 40);
+ vkvg_stroke(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
static bool fillAndStroke = true;
-void random_curves_stroke () {
- float w = (float)test_width;
- float h = (float)test_height;
+void random_curves_stroke() {
+ float w = (float)test_width;
+ float h = (float)test_height;
- VkvgContext ctx = _initCtx();
+ VkvgContext ctx = _initCtx();
- for (uint32_t i=0; i<test_size; i++) {
- randomize_color(ctx);
- float x1 = rndf() * w;
- float y1 = rndf() * h;
+ for (uint32_t i = 0; i < test_size; i++) {
+ randomize_color(ctx);
+ float x1 = rndf() * w;
+ float y1 = rndf() * h;
- vkvg_move_to (ctx, x1, y1);
- draw_random_curve(ctx);
+ vkvg_move_to(ctx, x1, y1);
+ draw_random_curve(ctx);
- vkvg_stroke (ctx);
- }
- vkvg_destroy(ctx);
+ vkvg_stroke(ctx);
+ }
+ vkvg_destroy(ctx);
}
-void _long_curv () {
- float w = (float)test_width;
- float h = (float)test_height;
+void _long_curv() {
+ float w = (float)test_width;
+ float h = (float)test_height;
- VkvgContext ctx = _initCtx();
+ VkvgContext ctx = _initCtx();
- randomize_color(ctx);
- float x1 = rndf() * w;
- float y1 = rndf() * h;
- vkvg_move_to (ctx, x1, y1);
+ randomize_color(ctx);
+ float x1 = rndf() * w;
+ float y1 = rndf() * h;
+ vkvg_move_to(ctx, x1, y1);
- for (uint32_t i=0; i<test_size; i++) {
- draw_random_curve(ctx);
- }
+ for (uint32_t i = 0; i < test_size; i++) {
+ draw_random_curve(ctx);
+ }
- if (fillAndStroke) {
- vkvg_fill_preserve(ctx);
- randomize_color(ctx);
- vkvg_stroke (ctx);
- }else
- vkvg_fill (ctx);
+ if (fillAndStroke) {
+ vkvg_fill_preserve(ctx);
+ randomize_color(ctx);
+ vkvg_stroke(ctx);
+ } else
+ vkvg_fill(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
-void long_curv_fill_nz () {
- fillAndStroke = false;
- fill_rule = VKVG_FILL_RULE_NON_ZERO;
- _long_curv ();
+void long_curv_fill_nz() {
+ fillAndStroke = false;
+ fill_rule = VKVG_FILL_RULE_NON_ZERO;
+ _long_curv();
}
-void long_curv_fill_eo () {
- fillAndStroke = false;
- fill_rule = VKVG_FILL_RULE_EVEN_ODD;
- _long_curv ();
+void long_curv_fill_eo() {
+ fillAndStroke = false;
+ fill_rule = VKVG_FILL_RULE_EVEN_ODD;
+ _long_curv();
}
-void long_curv_fill_stroke_nz () {
- fillAndStroke = true;
- fill_rule = VKVG_FILL_RULE_NON_ZERO;
- _long_curv ();
+void long_curv_fill_stroke_nz() {
+ fillAndStroke = true;
+ fill_rule = VKVG_FILL_RULE_NON_ZERO;
+ _long_curv();
}
-void long_curv_fill_stroke_eo () {
- fillAndStroke = true;
- fill_rule = VKVG_FILL_RULE_EVEN_ODD;
- _long_curv ();
+void long_curv_fill_stroke_eo() {
+ fillAndStroke = true;
+ fill_rule = VKVG_FILL_RULE_EVEN_ODD;
+ _long_curv();
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST(test3, argc, argv);
- //return 0;
- PERFORM_TEST(test, argc, argv);
- PERFORM_TEST(test2, argc, argv);
- PERFORM_TEST(curved_rect, argc, argv);
- //PERFORM_TEST(long_curv_fill_nz, argc, argv);
- no_test_size = false;
- PERFORM_TEST(long_curv_fill_eo, argc, argv);
- //PERFORM_TEST(long_curv_fill_stroke_nz, argc, argv);
- PERFORM_TEST(long_curv_fill_stroke_eo, argc, argv);
- PERFORM_TEST(random_curves_stroke, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(test3, argc, argv);
+ // return 0;
+ PERFORM_TEST(test, argc, argv);
+ PERFORM_TEST(test2, argc, argv);
+ PERFORM_TEST(curved_rect, argc, argv);
+ // PERFORM_TEST(long_curv_fill_nz, argc, argv);
+ no_test_size = false;
+ PERFORM_TEST(long_curv_fill_eo, argc, argv);
+ // PERFORM_TEST(long_curv_fill_stroke_nz, argc, argv);
+ PERFORM_TEST(long_curv_fill_stroke_eo, argc, argv);
+ PERFORM_TEST(random_curves_stroke, argc, argv);
+ return 0;
}
#include "test.h"
-void test(){
- dash_offset += 0.2f;
-
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
- vkvg_set_source_rgb(ctx, 1, 1, 1);
- vkvg_paint(ctx);
- //const float dashes[] = {160.0f, 80};
- //float dashes[] = {7.0f, 3};
- float dashes[] = {100, 20, 20, 20};
- vkvg_set_line_cap(ctx, VKVG_LINE_CAP_ROUND);
- vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND);
- vkvg_set_dash(ctx, dashes, 4, dash_offset);
- vkvg_set_line_width(ctx, 4);
- vkvg_set_source_rgb(ctx, 0, 0, 1);
-
- vkvg_move_to (ctx, 50, 50);
- vkvg_rel_line_to (ctx, 500, 0);
- vkvg_rel_line_to (ctx, 0, 200);
- vkvg_rel_line_to (ctx, 200, 0);
- vkvg_rel_line_to (ctx, 0, 500);
- vkvg_rel_line_to (ctx, -700, 0);
- vkvg_close_path(ctx);
- vkvg_stroke (ctx);
-
- dashes[0] = 0;
- dashes[1] = 20;
- vkvg_set_dash(ctx, dashes, 2, dash_offset);
-
- vkvg_set_source_rgb(ctx, 0, 1, 0);
-
- vkvg_move_to (ctx, 100, 100);
- vkvg_rel_line_to (ctx, 400, 0);
- vkvg_rel_line_to (ctx, 0, 200);
- vkvg_rel_line_to (ctx, 200, 0);
- vkvg_rel_line_to (ctx, 0, 400);
- vkvg_rel_line_to (ctx, -600, 0);
- vkvg_close_path(ctx);
- vkvg_stroke (ctx);
-
- dashes[0] = 80;
- dashes[1] = 20;
-
- vkvg_set_line_width(ctx, 10);
- vkvg_set_source_rgb(ctx, 1, 0, 0);
-
- vkvg_set_dash(ctx, dashes, 2, dash_offset);
-
- vkvg_rectangle(ctx, 200,300,200,200);
- /*vkvg_move_to(ctx, 200,300);
- vkvg_rel_line_to(ctx,200,0);*/
- vkvg_stroke (ctx);
-
- vkvg_destroy(ctx);
+void test() {
+ dash_offset += 0.2f;
+
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
+ vkvg_paint(ctx);
+ // const float dashes[] = {160.0f, 80};
+ // float dashes[] = {7.0f, 3};
+ float dashes[] = {100, 20, 20, 20};
+ vkvg_set_line_cap(ctx, VKVG_LINE_CAP_ROUND);
+ vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND);
+ vkvg_set_dash(ctx, dashes, 4, dash_offset);
+ vkvg_set_line_width(ctx, 4);
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+
+ vkvg_move_to(ctx, 50, 50);
+ vkvg_rel_line_to(ctx, 500, 0);
+ vkvg_rel_line_to(ctx, 0, 200);
+ vkvg_rel_line_to(ctx, 200, 0);
+ vkvg_rel_line_to(ctx, 0, 500);
+ vkvg_rel_line_to(ctx, -700, 0);
+ vkvg_close_path(ctx);
+ vkvg_stroke(ctx);
+
+ dashes[0] = 0;
+ dashes[1] = 20;
+ vkvg_set_dash(ctx, dashes, 2, dash_offset);
+
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+
+ vkvg_move_to(ctx, 100, 100);
+ vkvg_rel_line_to(ctx, 400, 0);
+ vkvg_rel_line_to(ctx, 0, 200);
+ vkvg_rel_line_to(ctx, 200, 0);
+ vkvg_rel_line_to(ctx, 0, 400);
+ vkvg_rel_line_to(ctx, -600, 0);
+ vkvg_close_path(ctx);
+ vkvg_stroke(ctx);
+
+ dashes[0] = 80;
+ dashes[1] = 20;
+
+ vkvg_set_line_width(ctx, 10);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+
+ vkvg_set_dash(ctx, dashes, 2, dash_offset);
+
+ vkvg_rectangle(ctx, 200, 300, 200, 200);
+ /*vkvg_move_to(ctx, 200,300);
+ vkvg_rel_line_to(ctx,200,0);*/
+ vkvg_stroke(ctx);
+
+ vkvg_destroy(ctx);
}
+void _long_curve() {
+ float w = (float)test_width;
+ float h = (float)test_height;
-void _long_curve () {
- float w = (float)test_width;
- float h = (float)test_height;
+ VkvgContext ctx = _initCtx();
- VkvgContext ctx = _initCtx();
+ randomize_color(ctx);
+ float x1 = w * rand() / RAND_MAX;
+ float y1 = h * rand() / RAND_MAX;
+ vkvg_move_to(ctx, x1, y1);
- randomize_color(ctx);
- float x1 = w*rand()/RAND_MAX;
- float y1 = h*rand()/RAND_MAX;
- vkvg_move_to (ctx, x1, y1);
-
- for (uint32_t i=0; i<test_size; i++)
- draw_random_curve(ctx);
-
- vkvg_stroke (ctx);
- vkvg_destroy(ctx);
+ for (uint32_t i = 0; i < test_size; i++)
+ draw_random_curve(ctx);
+ vkvg_stroke(ctx);
+ vkvg_destroy(ctx);
}
void _long_path() {
- float w = (float)test_width-10;
- float h = (float)test_height-10;
-
- VkvgContext ctx = _initCtx();
-
- randomize_color(ctx);
- float x1 = w*rndf();
- float y1 = h*rndf();
- vkvg_move_to (ctx, x1, y1);
- for (uint32_t i=0; i<test_size; i++) {
- x1 = w*rndf();
- y1 = h*rndf();
- vkvg_line_to (ctx, x1, y1);
- }
- vkvg_stroke (ctx);
- vkvg_destroy(ctx);
-}
-
-void path () {
- _long_path ();
-}
-void curve () {
- _long_curve ();
+ float w = (float)test_width - 10;
+ float h = (float)test_height - 10;
+
+ VkvgContext ctx = _initCtx();
+
+ randomize_color(ctx);
+ float x1 = w * rndf();
+ float y1 = h * rndf();
+ vkvg_move_to(ctx, x1, y1);
+ for (uint32_t i = 0; i < test_size; i++) {
+ x1 = w * rndf();
+ y1 = h * rndf();
+ vkvg_line_to(ctx, x1, y1);
+ }
+ vkvg_stroke(ctx);
+ vkvg_destroy(ctx);
}
-
-int main(int argc, char *argv[]) {
- dashes_count = 2;
- dashes[0] = 0;
- dashes[1] = 10;
- line_width = 4;
- //test_size = 50;
- line_cap = VKVG_LINE_CAP_ROUND;
- PERFORM_TEST(test, argc, argv);
- PERFORM_TEST(path, argc, argv);
- PERFORM_TEST(curve, argc, argv);
- return 0;
+void path() { _long_path(); }
+void curve() { _long_curve(); }
+
+int main(int argc, char *argv[]) {
+ dashes_count = 2;
+ dashes[0] = 0;
+ dashes[1] = 10;
+ line_width = 4;
+ // test_size = 50;
+ line_cap = VKVG_LINE_CAP_ROUND;
+ PERFORM_TEST(test, argc, argv);
+ PERFORM_TEST(path, argc, argv);
+ PERFORM_TEST(curve, argc, argv);
+ return 0;
}
#include "test.h"
-void test(){
- VkvgContext ctx = _initCtx(surf);
+void test() {
+ VkvgContext ctx = _initCtx(surf);
- vkvg_set_source_rgba(ctx,0.1f,0.9f,0.1f,1.0f);
- vkvg_move_to(ctx,100,100);
- vkvg_rel_line_to(ctx,50,200);
- vkvg_rel_line_to(ctx,150,-100);
- vkvg_rel_line_to(ctx,100,200);
- vkvg_rel_line_to(ctx,-100,100);
- vkvg_rel_line_to(ctx,-10,-100);
- vkvg_rel_line_to(ctx,-190,-50);
- vkvg_close_path(ctx);
+ vkvg_set_source_rgba(ctx, 0.1f, 0.9f, 0.1f, 1.0f);
+ vkvg_move_to(ctx, 100, 100);
+ vkvg_rel_line_to(ctx, 50, 200);
+ vkvg_rel_line_to(ctx, 150, -100);
+ vkvg_rel_line_to(ctx, 100, 200);
+ vkvg_rel_line_to(ctx, -100, 100);
+ vkvg_rel_line_to(ctx, -10, -100);
+ vkvg_rel_line_to(ctx, -190, -50);
+ vkvg_close_path(ctx);
- vkvg_fill(ctx);
+ vkvg_fill(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (test, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(test, argc, argv);
+ return 0;
}
#include "test.h"
-void test(){
- VkvgContext ctx = vkvg_create(surf);
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_move_to (ctx, 100, 100);
- vkvg_rel_line_to (ctx, 50, -80);
- vkvg_rel_line_to (ctx, 50, 80);
- vkvg_close_path (ctx);
+ vkvg_move_to(ctx, 100, 100);
+ vkvg_rel_line_to(ctx, 50, -80);
+ vkvg_rel_line_to(ctx, 50, 80);
+ vkvg_close_path(ctx);
- vkvg_move_to (ctx, 300, 100);
- vkvg_rel_line_to (ctx, 50, -80);
- vkvg_rel_line_to (ctx, 50, 80);
- vkvg_close_path (ctx);
+ vkvg_move_to(ctx, 300, 100);
+ vkvg_rel_line_to(ctx, 50, -80);
+ vkvg_rel_line_to(ctx, 50, 80);
+ vkvg_close_path(ctx);
- vkvg_set_line_width (ctx, 10.0);
- vkvg_set_source_rgb (ctx, 0, 0, 1);
- vkvg_fill_preserve (ctx);
- //vkvg_fill(ctx);
- vkvg_set_source_rgb (ctx, 1, 0, 0);
- vkvg_stroke (ctx);
+ vkvg_set_line_width(ctx, 10.0);
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_fill_preserve(ctx);
+ // vkvg_fill(ctx);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_stroke(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (test, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(test, argc, argv);
+ return 0;
}
#include "test.h"
-void test(){
- VkvgContext ctx = vkvg_create(surf);
- vkvg_save(ctx);
- vkvg_set_line_width(ctx,30);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_save(ctx);
+ vkvg_set_line_width(ctx, 30);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
- vkvg_set_source_rgba(ctx,0.1f,0.9f,0.1f,1.0f);
- vkvg_move_to(ctx,100,100);
- vkvg_rel_line_to(ctx,200,0);
- vkvg_rel_line_to(ctx,0,150);
- vkvg_rel_line_to(ctx,-200,0);
- vkvg_close_path(ctx);
+ vkvg_set_source_rgba(ctx, 0.1f, 0.9f, 0.1f, 1.0f);
+ vkvg_move_to(ctx, 100, 100);
+ vkvg_rel_line_to(ctx, 200, 0);
+ vkvg_rel_line_to(ctx, 0, 150);
+ vkvg_rel_line_to(ctx, -200, 0);
+ vkvg_close_path(ctx);
- vkvg_move_to(ctx,150,150);
- vkvg_rel_line_to(ctx,0,50);
- vkvg_rel_line_to(ctx,100,0);
- vkvg_rel_line_to(ctx,0,-50);
- vkvg_close_path(ctx);
+ vkvg_move_to(ctx, 150, 150);
+ vkvg_rel_line_to(ctx, 0, 50);
+ vkvg_rel_line_to(ctx, 100, 0);
+ vkvg_rel_line_to(ctx, 0, -50);
+ vkvg_close_path(ctx);
- vkvg_fill(ctx);
+ vkvg_fill(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (test, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(test, argc, argv);
+ return 0;
}
#include "test.h"
-VkvgPattern create_grad (VkvgContext ctx, float x) {
- VkvgPattern pat = vkvg_pattern_create_linear(x,0,300,0);
- vkvg_pattern_add_color_stop(pat, 0, 1, 0, 0, 1);
- vkvg_pattern_add_color_stop(pat, 0.5f, 0, 1, 0, 1);
- vkvg_pattern_add_color_stop(pat, 1, 0, 0, 1, 1);
- return pat;
+VkvgPattern create_grad(VkvgContext ctx, float x) {
+ VkvgPattern pat = vkvg_pattern_create_linear(x, 0, 300, 0);
+ vkvg_pattern_add_color_stop(pat, 0, 1, 0, 0, 1);
+ vkvg_pattern_add_color_stop(pat, 0.5f, 0, 1, 0, 1);
+ vkvg_pattern_add_color_stop(pat, 1, 0, 0, 1, 1);
+ return pat;
}
-void paint(){
- VkvgContext ctx = _initCtx (surf);
- //vkvg_translate(ctx,100,100);
- VkvgPattern pat = create_grad(ctx,0);
- //vkvg_pattern_set_extend(pat,VKVG_EXTEND_NONE);
- vkvg_rectangle(ctx, 0,0,400,460);
- vkvg_set_source (ctx, pat);
- vkvg_pattern_destroy (pat);
- vkvg_fill(ctx);
-
- float x = 100;
- pat = create_grad(ctx,x);
- //vkvg_pattern_set_extend(pat,VKVG_EXTEND_NONE);
- vkvg_rectangle(ctx, x,200,50,50);
- vkvg_set_source (ctx, pat);
- vkvg_pattern_destroy (pat);
- vkvg_fill(ctx);
-
- x+=100;
-
- pat = vkvg_pattern_create_linear(10,0,300,0);
- vkvg_pattern_add_color_stop(pat, 0, 0, 0, 1, 0);
- vkvg_pattern_add_color_stop(pat, 1, 1, 0, 0, 1);
- //vkvg_pattern_set_extend(pat,VKVG_EXTEND_NONE);
- vkvg_rectangle(ctx, 10,10,300,50);
- vkvg_set_source (ctx, pat);
- vkvg_pattern_destroy (pat);
- vkvg_fill(ctx);
-
- x+=200;
-
- pat = create_grad(ctx,x);
- //vkvg_pattern_set_extend(pat,VKVG_EXTEND_NONE);
- vkvg_rectangle(ctx, x,200,50,50);
- vkvg_set_source (ctx, pat);
- vkvg_pattern_destroy (pat);
- vkvg_fill(ctx);
-
- x+=100;
-
- pat = create_grad(ctx,x);
- //vkvg_pattern_set_extend(pat,VKVG_EXTEND_NONE);
- vkvg_rectangle(ctx, x,200,50,50);
- vkvg_set_source (ctx, pat);
- vkvg_pattern_destroy (pat);
- vkvg_fill(ctx);
-
- /*vkvg_set_source_rgb(ctx, 0,1,0);
- vkvg_rectangle(ctx, 100,100,200,160);
- vkvg_fill_preserve(ctx);
- vkvg_set_source_rgb(ctx, 0,0,0);
- vkvg_set_line_width(ctx,1.0f);
- vkvg_stroke(ctx);*/
-
-
- vkvg_destroy(ctx);
+void paint() {
+ VkvgContext ctx = _initCtx(surf);
+ // vkvg_translate(ctx,100,100);
+ VkvgPattern pat = create_grad(ctx, 0);
+ // vkvg_pattern_set_extend(pat,VKVG_EXTEND_NONE);
+ vkvg_rectangle(ctx, 0, 0, 400, 460);
+ vkvg_set_source(ctx, pat);
+ vkvg_pattern_destroy(pat);
+ vkvg_fill(ctx);
+
+ float x = 100;
+ pat = create_grad(ctx, x);
+ // vkvg_pattern_set_extend(pat,VKVG_EXTEND_NONE);
+ vkvg_rectangle(ctx, x, 200, 50, 50);
+ vkvg_set_source(ctx, pat);
+ vkvg_pattern_destroy(pat);
+ vkvg_fill(ctx);
+
+ x += 100;
+
+ pat = vkvg_pattern_create_linear(10, 0, 300, 0);
+ vkvg_pattern_add_color_stop(pat, 0, 0, 0, 1, 0);
+ vkvg_pattern_add_color_stop(pat, 1, 1, 0, 0, 1);
+ // vkvg_pattern_set_extend(pat,VKVG_EXTEND_NONE);
+ vkvg_rectangle(ctx, 10, 10, 300, 50);
+ vkvg_set_source(ctx, pat);
+ vkvg_pattern_destroy(pat);
+ vkvg_fill(ctx);
+
+ x += 200;
+
+ pat = create_grad(ctx, x);
+ // vkvg_pattern_set_extend(pat,VKVG_EXTEND_NONE);
+ vkvg_rectangle(ctx, x, 200, 50, 50);
+ vkvg_set_source(ctx, pat);
+ vkvg_pattern_destroy(pat);
+ vkvg_fill(ctx);
+
+ x += 100;
+
+ pat = create_grad(ctx, x);
+ // vkvg_pattern_set_extend(pat,VKVG_EXTEND_NONE);
+ vkvg_rectangle(ctx, x, 200, 50, 50);
+ vkvg_set_source(ctx, pat);
+ vkvg_pattern_destroy(pat);
+ vkvg_fill(ctx);
+
+ /*vkvg_set_source_rgb(ctx, 0,1,0);
+ vkvg_rectangle(ctx, 100,100,200,160);
+ vkvg_fill_preserve(ctx);
+ vkvg_set_source_rgb(ctx, 0,0,0);
+ vkvg_set_line_width(ctx,1.0f);
+ vkvg_stroke(ctx);*/
+
+ vkvg_destroy(ctx);
}
-void paint_repeat(){
- VkvgContext ctx = _initCtx (surf);
- VkvgPattern pat = create_grad(ctx,0);
- vkvg_pattern_set_extend(pat,VKVG_EXTEND_REPEAT);
- vkvg_set_source (ctx, pat);
- vkvg_pattern_destroy (pat);
- vkvg_paint(ctx);
-
- vkvg_destroy(ctx);
+void paint_repeat() {
+ VkvgContext ctx = _initCtx(surf);
+ VkvgPattern pat = create_grad(ctx, 0);
+ vkvg_pattern_set_extend(pat, VKVG_EXTEND_REPEAT);
+ vkvg_set_source(ctx, pat);
+ vkvg_pattern_destroy(pat);
+ vkvg_paint(ctx);
+
+ vkvg_destroy(ctx);
}
-void test(){
- VkvgContext ctx = _initCtx (surf);
- VkvgPattern pat = create_grad(ctx,0);
- vkvg_set_source (ctx, pat);
- vkvg_rectangle(ctx,100,100,200,200);
- vkvg_set_line_width(ctx, 20);
- //vkvg_fill (ctx);
- //vkvg_paint(ctx);
- vkvg_stroke (ctx);
- vkvg_pattern_destroy (pat);
-
- vkvg_destroy(ctx);
+void test() {
+ VkvgContext ctx = _initCtx(surf);
+ VkvgPattern pat = create_grad(ctx, 0);
+ vkvg_set_source(ctx, pat);
+ vkvg_rectangle(ctx, 100, 100, 200, 200);
+ vkvg_set_line_width(ctx, 20);
+ // vkvg_fill (ctx);
+ // vkvg_paint(ctx);
+ vkvg_stroke(ctx);
+ vkvg_pattern_destroy(pat);
+
+ vkvg_destroy(ctx);
}
-void test2(){
- VkvgContext ctx = _initCtx (surf);
-
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_paint(ctx);
-
- VkvgPattern pat = vkvg_pattern_create_linear(100,0,300,0);
- vkvg_set_line_width(ctx, 20);
- vkvg_pattern_add_color_stop(pat, 0, 1, 1, 1, 1);
- vkvg_pattern_add_color_stop(pat, 1, 1, 1, 0, 0);
- vkvg_set_source (ctx, pat);
- vkvg_rectangle(ctx,100,100,200,200);
- vkvg_fill (ctx);
- //vkvg_stroke (ctx);
- vkvg_pattern_destroy (pat);
-
- vkvg_destroy(ctx);
+void test2() {
+ VkvgContext ctx = _initCtx(surf);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+
+ VkvgPattern pat = vkvg_pattern_create_linear(100, 0, 300, 0);
+ vkvg_set_line_width(ctx, 20);
+ vkvg_pattern_add_color_stop(pat, 0, 1, 1, 1, 1);
+ vkvg_pattern_add_color_stop(pat, 1, 1, 1, 0, 0);
+ vkvg_set_source(ctx, pat);
+ vkvg_rectangle(ctx, 100, 100, 200, 200);
+ vkvg_fill(ctx);
+ // vkvg_stroke (ctx);
+ vkvg_pattern_destroy(pat);
+
+ vkvg_destroy(ctx);
}
void gradient_transform() {
- VkvgContext ctx = _initCtx (surf);
-
- //vkvg_translate(ctx,-100,-100);
-
- vkvg_translate(ctx, 200, 100);
- vkvg_rotate(ctx, 0.5f);
-
- //vkvg_scale(ctx,2,2);
- VkvgPattern pat = vkvg_pattern_create_linear(0, 0, 400, 0);
- vkvg_pattern_set_extend(pat, VKVG_EXTEND_NONE);
- vkvg_set_line_width(ctx, 20);
- vkvg_pattern_add_color_stop(pat, 0, 1, 0, 0, 1);
- vkvg_pattern_add_color_stop(pat, 0.5f, 0, 1, 0, 1);
- vkvg_pattern_add_color_stop(pat, 1, 0, 0, 1, 1);
- vkvg_set_source(ctx, pat);
- vkvg_rectangle(ctx, 0, 0, 400, 200);
- //vkvg_fill (ctx);
- vkvg_stroke(ctx);
- //vkvg_paint(ctx);
- vkvg_pattern_destroy(pat);
-
- vkvg_destroy(ctx);
+ VkvgContext ctx = _initCtx(surf);
+
+ // vkvg_translate(ctx,-100,-100);
+
+ vkvg_translate(ctx, 200, 100);
+ vkvg_rotate(ctx, 0.5f);
+
+ // vkvg_scale(ctx,2,2);
+ VkvgPattern pat = vkvg_pattern_create_linear(0, 0, 400, 0);
+ vkvg_pattern_set_extend(pat, VKVG_EXTEND_NONE);
+ vkvg_set_line_width(ctx, 20);
+ vkvg_pattern_add_color_stop(pat, 0, 1, 0, 0, 1);
+ vkvg_pattern_add_color_stop(pat, 0.5f, 0, 1, 0, 1);
+ vkvg_pattern_add_color_stop(pat, 1, 0, 0, 1, 1);
+ vkvg_set_source(ctx, pat);
+ vkvg_rectangle(ctx, 0, 0, 400, 200);
+ // vkvg_fill (ctx);
+ vkvg_stroke(ctx);
+ // vkvg_paint(ctx);
+ vkvg_pattern_destroy(pat);
+
+ vkvg_destroy(ctx);
}
void gradient_alpha() {
- VkvgContext ctx = _initCtx (surf);
- vkvg_set_source_rgb(ctx,0,1,0);
- vkvg_paint (ctx);
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_paint(ctx);
- VkvgPattern pat = vkvg_pattern_create_linear(10,0,300,0);
- vkvg_pattern_add_color_stop(pat, 1, 1, 0, 0, 0.5);
- vkvg_pattern_add_color_stop(pat, 1, 1, 0, 0, 0.5);
+ VkvgPattern pat = vkvg_pattern_create_linear(10, 0, 300, 0);
+ vkvg_pattern_add_color_stop(pat, 1, 1, 0, 0, 0.5);
+ vkvg_pattern_add_color_stop(pat, 1, 1, 0, 0, 0.5);
- vkvg_set_source (ctx, pat);
- vkvg_pattern_destroy (pat);
- vkvg_rectangle (ctx, 10, 10, 300, 200);
- vkvg_fill (ctx);
+ vkvg_set_source(ctx, pat);
+ vkvg_pattern_destroy(pat);
+ vkvg_rectangle(ctx, 10, 10, 300, 200);
+ vkvg_fill(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST(gradient_alpha, argc, argv);
- PERFORM_TEST(paint, argc, argv);
- PERFORM_TEST(paint_repeat, argc, argv);
- PERFORM_TEST(gradient_transform, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(gradient_alpha, argc, argv);
+ PERFORM_TEST(paint, argc, argv);
+ PERFORM_TEST(paint_repeat, argc, argv);
+ PERFORM_TEST(gradient_transform, argc, argv);
+ return 0;
}
#include "test.h"
#include "vectors.h"
-vkvg_fill_rule_t fillrule = VKVG_FILL_RULE_NON_ZERO;
-static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
-float lineWidth = 50.0f;
-vkvg_line_join_t lineJoin = VKVG_LINE_JOIN_MITER;
-vkvg_line_cap_t lineCap = VKVG_LINE_CAP_BUTT;
-bool isClosed = false;
-
-int ptsCount = 2;
-int initPtsCount = 4;
-vec2 pts[] = {
- {150,150},
- {250,150},
- {125,125},
- {145,125},
+vkvg_fill_rule_t fillrule = VKVG_FILL_RULE_NON_ZERO;
+static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
+float lineWidth = 50.0f;
+vkvg_line_join_t lineJoin = VKVG_LINE_JOIN_MITER;
+vkvg_line_cap_t lineCap = VKVG_LINE_CAP_BUTT;
+bool isClosed = false;
+
+int ptsCount = 2;
+int initPtsCount = 4;
+vec2 pts[] = {
+ {150, 150},
+ {250, 150},
+ {125, 125},
+ {145, 125},
};
-int hoverPt = -1;
+int hoverPt = -1;
double pointSize = 7;
static vkvg_pattern_type_t patternType = VKVG_PATTERN_TYPE_LINEAR;
-static VkEngine e;
-
-void draw (){
-
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
-
- VkvgPattern pat;
-
- switch (patternType) {
- case VKVG_PATTERN_TYPE_LINEAR:
- pat = vkvg_pattern_create_linear(pts[0].x,pts[0].y, pts[1].x,pts[1].y);
- break;
- case VKVG_PATTERN_TYPE_RADIAL:
- pat = vkvg_pattern_create_radial(
- pts[2].x,pts[2].y, vec2_length(vec2_sub(pts[3], pts[2])),
- pts[0].x,pts[0].y, vec2_length(vec2_sub(pts[1], pts[0]))
- );
- break;
- }
-
- /**/
-
- vkvg_pattern_add_color_stop(pat, 0.0, 1 ,0 ,0, 0.5);
- vkvg_pattern_add_color_stop(pat, 0.3, 0 ,1 ,0, 0.5);
- vkvg_pattern_add_color_stop(pat, 0.6, 0 ,0 ,1, 0.5);
- vkvg_pattern_add_color_stop(pat, 1.0, 0 ,0 ,0, 0.5);
-
- vkvg_set_source (ctx, pat);
- vkvg_paint (ctx);
-
- vkvg_set_dash(ctx, NULL, 0, 0);
- vkvg_set_line_width(ctx,1);
- for (int i=0; i<ptsCount; i++) {
- if (hoverPt == i)
- vkvg_set_source_rgba(ctx,0.5f,0.5f,1.0f,0.7f);
- else
- vkvg_set_source_rgba(ctx,1.0f,0.5f,0.5f,0.9f);
- vkvg_arc(ctx, pts[i].x, pts[i].y, pointSize, 0, M_PIF*2);
- vkvg_fill_preserve(ctx);
- vkvg_stroke(ctx);
- }
-
-
- vkvg_pattern_destroy (pat);
- vkvg_destroy (ctx);
+static VkEngine e;
+
+void draw() {
+
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+
+ VkvgPattern pat;
+
+ switch (patternType) {
+ case VKVG_PATTERN_TYPE_LINEAR:
+ pat = vkvg_pattern_create_linear(pts[0].x, pts[0].y, pts[1].x, pts[1].y);
+ break;
+ case VKVG_PATTERN_TYPE_RADIAL:
+ pat = vkvg_pattern_create_radial(pts[2].x, pts[2].y, vec2_length(vec2_sub(pts[3], pts[2])), pts[0].x, pts[0].y,
+ vec2_length(vec2_sub(pts[1], pts[0])));
+ break;
+ }
+
+ /**/
+
+ vkvg_pattern_add_color_stop(pat, 0.0, 1, 0, 0, 0.5);
+ vkvg_pattern_add_color_stop(pat, 0.3, 0, 1, 0, 0.5);
+ vkvg_pattern_add_color_stop(pat, 0.6, 0, 0, 1, 0.5);
+ vkvg_pattern_add_color_stop(pat, 1.0, 0, 0, 0, 0.5);
+
+ vkvg_set_source(ctx, pat);
+ vkvg_paint(ctx);
+
+ vkvg_set_dash(ctx, NULL, 0, 0);
+ vkvg_set_line_width(ctx, 1);
+ for (int i = 0; i < ptsCount; i++) {
+ if (hoverPt == i)
+ vkvg_set_source_rgba(ctx, 0.5f, 0.5f, 1.0f, 0.7f);
+ else
+ vkvg_set_source_rgba(ctx, 1.0f, 0.5f, 0.5f, 0.9f);
+ vkvg_arc(ctx, pts[i].x, pts[i].y, pointSize, 0, M_PIF * 2);
+ vkvg_fill_preserve(ctx);
+ vkvg_stroke(ctx);
+ }
+
+ vkvg_pattern_destroy(pat);
+ vkvg_destroy(ctx);
}
-static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
- if (action != GLFW_PRESS)
- return;
- switch (key) {
- case GLFW_KEY_ESCAPE :
- glfwSetWindowShouldClose(window, GLFW_TRUE);
- break;
- case GLFW_KEY_P :
- patternType++;
- if (patternType > VKVG_PATTERN_TYPE_RADIAL)
- patternType = VKVG_PATTERN_TYPE_LINEAR;
- break;
- case GLFW_KEY_S :
- vkengine_wait_idle(e);
- vkvg_surface_write_to_png(surf, "/home/jp/test.png");
- break;
- case GLFW_KEY_KP_ADD :
- if (ptsCount < initPtsCount)
- ptsCount++;
- break;
- case GLFW_KEY_KP_SUBTRACT :
- if (ptsCount > 1)
- ptsCount--;
- break;
- }
+static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+ if (action != GLFW_PRESS)
+ return;
+ switch (key) {
+ case GLFW_KEY_ESCAPE:
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+ break;
+ case GLFW_KEY_P:
+ patternType++;
+ if (patternType > VKVG_PATTERN_TYPE_RADIAL)
+ patternType = VKVG_PATTERN_TYPE_LINEAR;
+ break;
+ case GLFW_KEY_S:
+ vkengine_wait_idle(e);
+ vkvg_surface_write_to_png(surf, "/home/jp/test.png");
+ break;
+ case GLFW_KEY_KP_ADD:
+ if (ptsCount < initPtsCount)
+ ptsCount++;
+ break;
+ case GLFW_KEY_KP_SUBTRACT:
+ if (ptsCount > 1)
+ ptsCount--;
+ break;
+ }
}
-static void mouse_move_callback(GLFWwindow* window, double x, double y){
- if (mouseDown) {
- if (hoverPt < 0)
- return;
- pts[hoverPt].x = x;
- pts[hoverPt].y = y;
- } else {
- for (int i=0; i<ptsCount; i++) {
- if (x > pts[i].x - pointSize &&
- x < pts[i].x + pointSize &&
- y > pts[i].y - pointSize &&
- y < pts[i].y + pointSize) {
- hoverPt = i;
- return;
- }
- }
- hoverPt = -1;
- }
+static void mouse_move_callback(GLFWwindow *window, double x, double y) {
+ if (mouseDown) {
+ if (hoverPt < 0)
+ return;
+ pts[hoverPt].x = x;
+ pts[hoverPt].y = y;
+ } else {
+ for (int i = 0; i < ptsCount; i++) {
+ if (x > pts[i].x - pointSize && x < pts[i].x + pointSize && y > pts[i].y - pointSize &&
+ y < pts[i].y + pointSize) {
+ hoverPt = i;
+ return;
+ }
+ }
+ hoverPt = -1;
+ }
}
-static void scroll_callback(GLFWwindow* window, double x, double y){
- if (y<0.f)
- zoom *= 0.5f;
- else
- zoom *= 2.0f;
+static void scroll_callback(GLFWwindow *window, double x, double y) {
+ if (y < 0.f)
+ zoom *= 0.5f;
+ else
+ zoom *= 2.0f;
}
-static void mouse_button_callback(GLFWwindow* window, int but, int state, int modif){
- if (but != GLFW_MOUSE_BUTTON_1)
- return;
- if (state == GLFW_TRUE)
- mouseDown = true;
- else
- mouseDown = false;
+static void mouse_button_callback(GLFWwindow *window, int but, int state, int modif) {
+ if (but != GLFW_MOUSE_BUTTON_1)
+ return;
+ if (state == GLFW_TRUE)
+ mouseDown = true;
+ else
+ mouseDown = false;
}
+int main(int argc, char *argv[]) {
+ _parse_args(argc, argv);
-int main(int argc, char* argv[]) {
+ e = vkengine_create(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
- _parse_args (argc, argv);
+ VkhPresenter r = e->renderer;
+ vkengine_set_key_callback(e, key_callback);
+ vkengine_set_mouse_but_callback(e, mouse_button_callback);
+ vkengine_set_cursor_pos_callback(e, mouse_move_callback);
+ vkengine_set_scroll_callback(e, scroll_callback);
- e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
+ vkvg_device_create_info_t info = {samples, false, vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0};
+ device = vkvg_device_create(&info);
+ surf = vkvg_surface_create(device, test_width, test_height);
- VkhPresenter r = e->renderer;
- vkengine_set_key_callback (e, key_callback);
- vkengine_set_mouse_but_callback(e, mouse_button_callback);
- vkengine_set_cursor_pos_callback(e, mouse_move_callback);
- vkengine_set_scroll_callback(e, scroll_callback);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
- vkvg_device_create_info_t info = {
- samples,
- false,
- vkh_app_get_inst(e->app),
- r->dev->phy,
- r->dev->dev,
- r->qFam,
- 0
- };
- device = vkvg_device_create(&info);
- surf = vkvg_surface_create(device, test_width, test_height);
+ while (!vkengine_should_close(e)) {
+ glfwPollEvents();
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ draw();
- while (!vkengine_should_close (e)) {
- glfwPollEvents();
+ if (!vkh_presenter_draw(r)) {
+ vkh_presenter_get_size(r, &test_width, &test_height);
+ vkvg_surface_destroy(surf);
+ surf = vkvg_surface_create(device, test_width, test_height);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ vkDeviceWaitIdle(r->dev->dev);
+ continue;
+ }
+ }
+ vkDeviceWaitIdle(e->dev->dev);
- draw ();
+ vkvg_surface_destroy(surf);
- if (!vkh_presenter_draw (r)){
- vkh_presenter_get_size (r, &test_width, &test_height);
- vkvg_surface_destroy (surf);
- surf = vkvg_surface_create(device, test_width, test_height);
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
- vkDeviceWaitIdle(r->dev->dev);
- continue;
- }
- }
- vkDeviceWaitIdle(e->dev->dev);
+ vkvg_device_destroy(device);
- vkvg_surface_destroy (surf);
+ vkengine_destroy(e);
- vkvg_device_destroy (device);
-
- vkengine_destroy (e);
-
- return 0;
+ return 0;
}
#include "test.h"
-const char* imgPath = "data/miroir.jpg";
-void paint () {
- VkvgContext ctx = vkvg_create(surf);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+const char *imgPath = "data/miroir.jpg";
+void paint() {
+ VkvgContext ctx = vkvg_create(surf);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- vkvg_set_source_surface(ctx, imgSurf, 0, 0);
- vkvg_paint(ctx);
+ vkvg_set_source_surface(ctx, imgSurf, 0, 0);
+ vkvg_paint(ctx);
- vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+ vkvg_surface_destroy(imgSurf);
+ vkvg_destroy(ctx);
}
-void paint_offset () {
- VkvgContext ctx = vkvg_create(surf);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+void paint_offset() {
+ VkvgContext ctx = vkvg_create(surf);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- vkvg_set_source_surface(ctx, imgSurf, 100, 100);
- vkvg_paint(ctx);
+ vkvg_set_source_surface(ctx, imgSurf, 100, 100);
+ vkvg_paint(ctx);
- vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+ vkvg_surface_destroy(imgSurf);
+ vkvg_destroy(ctx);
}
-void paint_with_scale(){
- VkvgContext ctx = vkvg_create(surf);
- vkvg_scale (ctx, 0.2f,0.2f);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- vkvg_set_source_surface(ctx, imgSurf, 0, 0);
+void paint_with_scale() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_scale(ctx, 0.2f, 0.2f);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ vkvg_set_source_surface(ctx, imgSurf, 0, 0);
- vkvg_paint(ctx);
+ vkvg_paint(ctx);
- vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+ vkvg_surface_destroy(imgSurf);
+ vkvg_destroy(ctx);
}
-void translate(){
- VkvgContext ctx = vkvg_create(surf);
- vkvg_translate (ctx, 150,50);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- vkvg_set_source_surface(ctx, imgSurf, 0, 0);
+void translate() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_translate(ctx, 150, 50);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ vkvg_set_source_surface(ctx, imgSurf, 0, 0);
- vkvg_paint(ctx);
+ vkvg_paint(ctx);
- vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+ vkvg_surface_destroy(imgSurf);
+ vkvg_destroy(ctx);
}
-void offset_and_scale(){
- VkvgContext ctx = vkvg_create(surf);
- vkvg_scale (ctx, 0.2f,0.2f);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- vkvg_set_source_surface(ctx, imgSurf, 100, 100);
+void offset_and_scale() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_scale(ctx, 0.2f, 0.2f);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ vkvg_set_source_surface(ctx, imgSurf, 100, 100);
- vkvg_paint(ctx);
+ vkvg_paint(ctx);
- vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+ vkvg_surface_destroy(imgSurf);
+ vkvg_destroy(ctx);
}
static float angle = 0;
-void paint_with_rot(){
- angle += 0.005;
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
+void paint_with_rot() {
+ angle += 0.005;
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
- vkvg_rotate (ctx, angle);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- vkvg_set_source_surface(ctx, imgSurf, 0, 0);
+ vkvg_rotate(ctx, angle);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ vkvg_set_source_surface(ctx, imgSurf, 0, 0);
- vkvg_paint(ctx);
+ vkvg_paint(ctx);
- vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+ vkvg_surface_destroy(imgSurf);
+ vkvg_destroy(ctx);
}
-void offset_and_rot(){
- angle += 0.005;
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
+void offset_and_rot() {
+ angle += 0.005;
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
- vkvg_rotate (ctx, angle);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- vkvg_set_source_surface(ctx, imgSurf, 100, 100);
+ vkvg_rotate(ctx, angle);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ vkvg_set_source_surface(ctx, imgSurf, 100, 100);
- vkvg_paint(ctx);
+ vkvg_paint(ctx);
- vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+ vkvg_surface_destroy(imgSurf);
+ vkvg_destroy(ctx);
}
-void paint_pattern () {
- VkvgContext ctx = vkvg_create(surf);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
- vkvg_set_source(ctx, pat);
- vkvg_paint(ctx);
- vkvg_pattern_destroy(pat);
- vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+void paint_pattern() {
+ VkvgContext ctx = vkvg_create(surf);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
+ vkvg_set_source(ctx, pat);
+ vkvg_paint(ctx);
+ vkvg_pattern_destroy(pat);
+ vkvg_surface_destroy(imgSurf);
+ vkvg_destroy(ctx);
}
-void paint_patt_repeat () {
- VkvgContext ctx = vkvg_create(surf);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
- vkvg_pattern_set_extend(pat,VKVG_EXTEND_REPEAT);
- vkvg_set_source(ctx, pat);
- vkvg_paint(ctx);
- vkvg_pattern_destroy(pat);
- vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+void paint_patt_repeat() {
+ VkvgContext ctx = vkvg_create(surf);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
+ vkvg_pattern_set_extend(pat, VKVG_EXTEND_REPEAT);
+ vkvg_set_source(ctx, pat);
+ vkvg_paint(ctx);
+ vkvg_pattern_destroy(pat);
+ vkvg_surface_destroy(imgSurf);
+ vkvg_destroy(ctx);
}
-void paint_patt_repeat_scalled () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_scale (ctx, 0.2f,0.2f);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
- vkvg_pattern_set_extend(pat,VKVG_EXTEND_REPEAT);
- vkvg_set_source(ctx, pat);
- vkvg_paint(ctx);
- vkvg_pattern_destroy(pat);
- vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+void paint_patt_repeat_scalled() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_scale(ctx, 0.2f, 0.2f);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
+ vkvg_pattern_set_extend(pat, VKVG_EXTEND_REPEAT);
+ vkvg_set_source(ctx, pat);
+ vkvg_paint(ctx);
+ vkvg_pattern_destroy(pat);
+ vkvg_surface_destroy(imgSurf);
+ vkvg_destroy(ctx);
}
-void paint_patt_pad () {
- VkvgContext ctx = vkvg_create(surf);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
- vkvg_pattern_set_extend(pat,VKVG_EXTEND_PAD);
- vkvg_set_source(ctx, pat);
- vkvg_paint(ctx);
- vkvg_pattern_destroy(pat);
- vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+void paint_patt_pad() {
+ VkvgContext ctx = vkvg_create(surf);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
+ vkvg_pattern_set_extend(pat, VKVG_EXTEND_PAD);
+ vkvg_set_source(ctx, pat);
+ vkvg_paint(ctx);
+ vkvg_pattern_destroy(pat);
+ vkvg_surface_destroy(imgSurf);
+ vkvg_destroy(ctx);
}
-void test(){
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_fill_rule(ctx,VKVG_FILL_RULE_EVEN_ODD);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- vkvg_translate(ctx,200,200);
- //vkvg_rotate(ctx,M_PI_4);
+ vkvg_translate(ctx, 200, 200);
+ // vkvg_rotate(ctx,M_PI_4);
- vkvg_set_line_width(ctx,20.f);
- //vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_arc(ctx,200,200,200,0,2.f*M_PIF);
- vkvg_new_sub_path(ctx);
- vkvg_arc(ctx,200,200,100,0,2.f*M_PIF);
+ vkvg_set_line_width(ctx, 20.f);
+ // vkvg_set_source_rgba(ctx,1,0,0,1);
+ vkvg_arc(ctx, 200, 200, 200, 0, 2.f * M_PIF);
+ vkvg_new_sub_path(ctx);
+ vkvg_arc(ctx, 200, 200, 100, 0, 2.f * M_PIF);
- vkvg_set_source_surface(ctx, imgSurf, 0, 0);
- vkvg_fill_preserve(ctx);
- vkvg_set_source_rgba(ctx,0.2f,0.3f,0.8f,1);
+ vkvg_set_source_surface(ctx, imgSurf, 0, 0);
+ vkvg_fill_preserve(ctx);
+ vkvg_set_source_rgba(ctx, 0.2f, 0.3f, 0.8f, 1);
- vkvg_stroke(ctx);
+ vkvg_stroke(ctx);
- vkvg_surface_destroy(imgSurf);
+ vkvg_surface_destroy(imgSurf);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (paint, argc, argv);
- PERFORM_TEST (paint_offset, argc, argv);
- PERFORM_TEST (paint_with_scale, argc, argv);
- PERFORM_TEST (offset_and_scale, argc, argv);
- PERFORM_TEST (translate, argc, argv);
- PERFORM_TEST (paint_with_rot, argc, argv);
- PERFORM_TEST (offset_and_rot, argc, argv);
- PERFORM_TEST (paint_pattern, argc, argv);
- PERFORM_TEST (paint_patt_repeat, argc, argv);
- PERFORM_TEST (paint_patt_repeat_scalled, argc, argv);
- PERFORM_TEST (paint_patt_pad, argc, argv);
- PERFORM_TEST (test, argc, argv);
-
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(paint, argc, argv);
+ PERFORM_TEST(paint_offset, argc, argv);
+ PERFORM_TEST(paint_with_scale, argc, argv);
+ PERFORM_TEST(offset_and_scale, argc, argv);
+ PERFORM_TEST(translate, argc, argv);
+ PERFORM_TEST(paint_with_rot, argc, argv);
+ PERFORM_TEST(offset_and_rot, argc, argv);
+ PERFORM_TEST(paint_pattern, argc, argv);
+ PERFORM_TEST(paint_patt_repeat, argc, argv);
+ PERFORM_TEST(paint_patt_repeat_scalled, argc, argv);
+ PERFORM_TEST(paint_patt_pad, argc, argv);
+ PERFORM_TEST(test, argc, argv);
+
+ return 0;
}
#include "test.h"
#include "vectors.h"
-vkvg_fill_rule_t fillrule = VKVG_FILL_RULE_NON_ZERO;
-static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
-float lineWidth = 50.0f;
-vkvg_line_join_t lineJoin = VKVG_LINE_JOIN_MITER;
-vkvg_line_cap_t lineCap = VKVG_LINE_CAP_BUTT;
-bool isClosed = false;
-bool startWithArc = false, endWithArc = false;
-
-int ptsCount = 4;
-int initPtsCount = 5;
-vec2 pts[] = {
- {150,150},
- {200,300},
- {250,150},
- {280,350},
- {300,100},
+vkvg_fill_rule_t fillrule = VKVG_FILL_RULE_NON_ZERO;
+static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
+float lineWidth = 50.0f;
+vkvg_line_join_t lineJoin = VKVG_LINE_JOIN_MITER;
+vkvg_line_cap_t lineCap = VKVG_LINE_CAP_BUTT;
+bool isClosed = false;
+bool startWithArc = false, endWithArc = false;
+
+int ptsCount = 4;
+int initPtsCount = 5;
+vec2 pts[] = {
+ {150, 150}, {200, 300}, {250, 150}, {280, 350}, {300, 100},
};
/*vec2 pts[] = {
- {150,150},
- {250,150},
- {100,150},
- {150,200},
+ {150,150},
+ {250,150},
+ {100,150},
+ {150,200},
};*/
-int hoverPt = -1;
+int hoverPt = -1;
double pointSize = 7;
-float dash[] = {0, 60};
+float dash[] = {0, 60};
uint32_t dashCountInit = 2;
-uint32_t dashCount = 0;
-float miterLimit = 10.0f;
-
-
-
-void draw (){
-
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
- if (dashCount > 0)
- vkvg_set_dash(ctx, dash, dashCount,0);
- vkvg_set_source_rgba (ctx,1,0,0,0.3f);
- vkvg_set_line_width (ctx,lineWidth);
- vkvg_set_line_join (ctx, lineJoin);
- vkvg_set_line_cap (ctx, lineCap);
- vkvg_set_miter_limit (ctx, miterLimit);
-
- if (startWithArc)
- vkvg_arc_negative(ctx,pts[0].x,pts[0].y,200, M_PIF*1.5f, M_PIF);
- else
- vkvg_move_to(ctx,pts[0].x,pts[0].y);
- for (int i=1; i<ptsCount-1; i++)
- vkvg_line_to(ctx,pts[i].x,pts[i].y);
- if (endWithArc)
- vkvg_arc_negative(ctx,pts[ptsCount-1].x,pts[ptsCount-1].y,200, M_PIF*1.5f, M_PIF);
- else
- vkvg_line_to(ctx,pts[ptsCount-1].x,pts[ptsCount-1].y);
-
- if (isClosed)
- vkvg_close_path(ctx);
-
- if (hoverPt>=0) {
- vkvg_stroke_preserve(ctx);
- vkvg_set_dash(ctx, NULL, 0, 0);
- vkvg_set_line_width(ctx,2);
- vkvg_set_source_rgba(ctx,0,0,0,1);
- vkvg_stroke(ctx);
- vkvg_set_source_rgba(ctx,0.5f,0.5f,1.0f,0.7f);
- vkvg_arc (ctx, pts[hoverPt].x, pts[hoverPt].y, pointSize, 0, M_PIF*2);
- vkvg_fill_preserve(ctx);
- vkvg_stroke(ctx);
- } else
- vkvg_stroke(ctx);
-
- //draw_v(ctx, 200, 20, VKVG_LINE_JOIN_BEVEL);
- //draw_v(ctx, 300, 80, VKVG_LINE_JOIN_ROUND);
- vkvg_destroy(ctx);
+uint32_t dashCount = 0;
+float miterLimit = 10.0f;
+
+void draw() {
+
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+ if (dashCount > 0)
+ vkvg_set_dash(ctx, dash, dashCount, 0);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.3f);
+ vkvg_set_line_width(ctx, lineWidth);
+ vkvg_set_line_join(ctx, lineJoin);
+ vkvg_set_line_cap(ctx, lineCap);
+ vkvg_set_miter_limit(ctx, miterLimit);
+
+ if (startWithArc)
+ vkvg_arc_negative(ctx, pts[0].x, pts[0].y, 200, M_PIF * 1.5f, M_PIF);
+ else
+ vkvg_move_to(ctx, pts[0].x, pts[0].y);
+ for (int i = 1; i < ptsCount - 1; i++)
+ vkvg_line_to(ctx, pts[i].x, pts[i].y);
+ if (endWithArc)
+ vkvg_arc_negative(ctx, pts[ptsCount - 1].x, pts[ptsCount - 1].y, 200, M_PIF * 1.5f, M_PIF);
+ else
+ vkvg_line_to(ctx, pts[ptsCount - 1].x, pts[ptsCount - 1].y);
+
+ if (isClosed)
+ vkvg_close_path(ctx);
+
+ if (hoverPt >= 0) {
+ vkvg_stroke_preserve(ctx);
+ vkvg_set_dash(ctx, NULL, 0, 0);
+ vkvg_set_line_width(ctx, 2);
+ vkvg_set_source_rgba(ctx, 0, 0, 0, 1);
+ vkvg_stroke(ctx);
+ vkvg_set_source_rgba(ctx, 0.5f, 0.5f, 1.0f, 0.7f);
+ vkvg_arc(ctx, pts[hoverPt].x, pts[hoverPt].y, pointSize, 0, M_PIF * 2);
+ vkvg_fill_preserve(ctx);
+ vkvg_stroke(ctx);
+ } else
+ vkvg_stroke(ctx);
+
+ // draw_v(ctx, 200, 20, VKVG_LINE_JOIN_BEVEL);
+ // draw_v(ctx, 300, 80, VKVG_LINE_JOIN_ROUND);
+ vkvg_destroy(ctx);
}
-static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
- if (action == GLFW_RELEASE)
- return;
- switch (key) {
- case GLFW_KEY_ESCAPE :
- glfwSetWindowShouldClose(window, GLFW_TRUE);
- break;
- case GLFW_KEY_W :
- isClosed ^= true;
- break;
- case GLFW_KEY_Q :
- startWithArc ^= true;
- break;
- case GLFW_KEY_A :
- endWithArc ^= true;
- break;
- case GLFW_KEY_J :
- lineJoin++;
- if (lineJoin > 2)
- lineJoin = 0;
- break;
- case GLFW_KEY_C :
- lineCap++;
- if (lineCap > 2)
- lineCap = 0;
- break;
- case GLFW_KEY_D :
- if (dashCount == 0)
- dashCount = dashCountInit;
- else
- dashCount = 0;
- break;
- case GLFW_KEY_E :
- if (dash[0] > 0)
- dash[0] = 0;
- else
- dash[0] = 80;
- break;
- case GLFW_KEY_L :
- if (mods & GLFW_MOD_SHIFT)
- miterLimit /= 2.0f;
- else
- miterLimit *= 2.0f;
- break;
- case GLFW_KEY_P :
- if (mods & GLFW_MOD_SHIFT) {
- if (ptsCount > 1)
- ptsCount--;
- } else {
- if (ptsCount < initPtsCount)
- ptsCount++;
- }
- break;
- case GLFW_KEY_KP_ADD :
- lineWidth++;
- break;
- case GLFW_KEY_KP_SUBTRACT :
- if (lineWidth > 1)
- lineWidth--;
- break;
- }
+static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+ if (action == GLFW_RELEASE)
+ return;
+ switch (key) {
+ case GLFW_KEY_ESCAPE:
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+ break;
+ case GLFW_KEY_W:
+ isClosed ^= true;
+ break;
+ case GLFW_KEY_Q:
+ startWithArc ^= true;
+ break;
+ case GLFW_KEY_A:
+ endWithArc ^= true;
+ break;
+ case GLFW_KEY_J:
+ lineJoin++;
+ if (lineJoin > 2)
+ lineJoin = 0;
+ break;
+ case GLFW_KEY_C:
+ lineCap++;
+ if (lineCap > 2)
+ lineCap = 0;
+ break;
+ case GLFW_KEY_D:
+ if (dashCount == 0)
+ dashCount = dashCountInit;
+ else
+ dashCount = 0;
+ break;
+ case GLFW_KEY_E:
+ if (dash[0] > 0)
+ dash[0] = 0;
+ else
+ dash[0] = 80;
+ break;
+ case GLFW_KEY_L:
+ if (mods & GLFW_MOD_SHIFT)
+ miterLimit /= 2.0f;
+ else
+ miterLimit *= 2.0f;
+ break;
+ case GLFW_KEY_P:
+ if (mods & GLFW_MOD_SHIFT) {
+ if (ptsCount > 1)
+ ptsCount--;
+ } else {
+ if (ptsCount < initPtsCount)
+ ptsCount++;
+ }
+ break;
+ case GLFW_KEY_KP_ADD:
+ lineWidth++;
+ break;
+ case GLFW_KEY_KP_SUBTRACT:
+ if (lineWidth > 1)
+ lineWidth--;
+ break;
+ }
}
-static void mouse_move_callback(GLFWwindow* window, double x, double y){
- if (mouseDown) {
- if (hoverPt < 0)
- return;
- pts[hoverPt].x = x;
- pts[hoverPt].y = y;
- } else {
- for (int i=0; i<ptsCount; i++) {
- if (x > pts[i].x - pointSize &&
- x < pts[i].x + pointSize &&
- y > pts[i].y - pointSize &&
- y < pts[i].y + pointSize) {
- hoverPt = i;
- return;
- }
- }
- hoverPt = -1;
- }
+static void mouse_move_callback(GLFWwindow *window, double x, double y) {
+ if (mouseDown) {
+ if (hoverPt < 0)
+ return;
+ pts[hoverPt].x = x;
+ pts[hoverPt].y = y;
+ } else {
+ for (int i = 0; i < ptsCount; i++) {
+ if (x > pts[i].x - pointSize && x < pts[i].x + pointSize && y > pts[i].y - pointSize &&
+ y < pts[i].y + pointSize) {
+ hoverPt = i;
+ return;
+ }
+ }
+ hoverPt = -1;
+ }
}
-static void scroll_callback(GLFWwindow* window, double x, double y){
- if (y<0.f)
- zoom *= 0.5f;
- else
- zoom *= 2.0f;
+static void scroll_callback(GLFWwindow *window, double x, double y) {
+ if (y < 0.f)
+ zoom *= 0.5f;
+ else
+ zoom *= 2.0f;
}
-static void mouse_button_callback(GLFWwindow* window, int but, int state, int modif){
- if (but != GLFW_MOUSE_BUTTON_1)
- return;
- if (state == GLFW_TRUE)
- mouseDown = true;
- else
- mouseDown = false;
+static void mouse_button_callback(GLFWwindow *window, int but, int state, int modif) {
+ if (but != GLFW_MOUSE_BUTTON_1)
+ return;
+ if (state == GLFW_TRUE)
+ mouseDown = true;
+ else
+ mouseDown = false;
}
+int main(int argc, char *argv[]) {
+ _parse_args(argc, argv);
+ VkEngine e;
+ e = vkengine_create(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
-int main(int argc, char* argv[]) {
+ VkhPresenter r = e->renderer;
+ vkengine_set_key_callback(e, key_callback);
+ vkengine_set_mouse_but_callback(e, mouse_button_callback);
+ vkengine_set_cursor_pos_callback(e, mouse_move_callback);
+ vkengine_set_scroll_callback(e, scroll_callback);
- _parse_args (argc, argv);
- VkEngine e;
- e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
+ vkvg_device_create_info_t info = {samples, false, vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0};
+ device = vkvg_device_create(&info);
+ surf = vkvg_surface_create(device, test_width, test_height);
- VkhPresenter r = e->renderer;
- vkengine_set_key_callback (e, key_callback);
- vkengine_set_mouse_but_callback(e, mouse_button_callback);
- vkengine_set_cursor_pos_callback(e, mouse_move_callback);
- vkengine_set_scroll_callback(e, scroll_callback);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
- vkvg_device_create_info_t info = {
- samples,
- false,
- vkh_app_get_inst(e->app),
- r->dev->phy,
- r->dev->dev,
- r->qFam,
- 0
- };
- device = vkvg_device_create(&info);
- surf = vkvg_surface_create(device, test_width, test_height);
+ while (!vkengine_should_close(e)) {
+ glfwPollEvents();
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ draw();
- while (!vkengine_should_close (e)) {
- glfwPollEvents();
+ if (!vkh_presenter_draw(r)) {
+ vkh_presenter_get_size(r, &test_width, &test_height);
+ vkvg_surface_destroy(surf);
+ surf = vkvg_surface_create(device, test_width, test_height);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ vkDeviceWaitIdle(r->dev->dev);
+ continue;
+ }
+ }
+ vkDeviceWaitIdle(e->dev->dev);
- draw ();
+ vkvg_surface_destroy(surf);
- if (!vkh_presenter_draw (r)){
- vkh_presenter_get_size (r, &test_width, &test_height);
- vkvg_surface_destroy (surf);
- surf = vkvg_surface_create(device, test_width, test_height);
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
- vkDeviceWaitIdle(r->dev->dev);
- continue;
- }
- }
- vkDeviceWaitIdle(e->dev->dev);
+ vkvg_device_destroy(device);
- vkvg_surface_destroy (surf);
+ vkengine_destroy(e);
- vkvg_device_destroy (device);
-
- vkengine_destroy (e);
-
- return 0;
+ return 0;
}
#include "test.h"
-void test(){
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgba(ctx,0.9f,0.9f,0.9f,1);
- vkvg_paint(ctx);
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_source_rgba(ctx, 0.9f, 0.9f, 0.9f, 1);
+ vkvg_paint(ctx);
- float x = 20, y = 20, dx = 40, dy = 60;
+ float x = 20, y = 20, dx = 40, dy = 60;
- //vkvg_scale(ctx,5,5);
- vkvg_set_line_width(ctx,30);
- vkvg_set_source_rgba(ctx,0.0,0.0,0,1);
- vkvg_move_to(ctx,x,y);
- vkvg_rel_line_to(ctx,0,dy);
- vkvg_stroke(ctx);
- vkvg_set_line_cap(ctx,VKVG_LINE_CAP_SQUARE);
- vkvg_move_to(ctx,x+dx,y);
- vkvg_rel_line_to(ctx,0,dy);
- vkvg_stroke(ctx);
- vkvg_set_line_cap(ctx,VKVG_LINE_CAP_ROUND);
- vkvg_move_to(ctx,x+2*dx,y);
- vkvg_rel_line_to(ctx,0,dy);
- vkvg_rel_move_to(ctx,dx,-dy);
- vkvg_rel_line_to(ctx,dx,dy);
- vkvg_rel_move_to(ctx,dx,-dy/2.f);
- vkvg_rel_line_to(ctx,dx,0);
- vkvg_rel_move_to(ctx,dx,dy/2.f);
- vkvg_rel_line_to(ctx,dx,-dy);
- vkvg_rel_move_to(ctx,dx,dy);
- vkvg_rel_line_to(ctx,0,-dy);
- vkvg_rel_move_to(ctx,dx*2.f,dy);
- vkvg_rel_line_to(ctx,-dx,-dy);
- vkvg_rel_move_to(ctx,dx*3.f,dy/2.f);
- vkvg_rel_line_to(ctx,-dx,0);
- //vkvg_rel_line_to(ctx,0,-dy);
- //vkvg_rel_move_to(ctx,dx,dy/2);
- //vkvg_rel_line_to(ctx,dx,0);
- vkvg_stroke(ctx);
+ // vkvg_scale(ctx,5,5);
+ vkvg_set_line_width(ctx, 30);
+ vkvg_set_source_rgba(ctx, 0.0, 0.0, 0, 1);
+ vkvg_move_to(ctx, x, y);
+ vkvg_rel_line_to(ctx, 0, dy);
+ vkvg_stroke(ctx);
+ vkvg_set_line_cap(ctx, VKVG_LINE_CAP_SQUARE);
+ vkvg_move_to(ctx, x + dx, y);
+ vkvg_rel_line_to(ctx, 0, dy);
+ vkvg_stroke(ctx);
+ vkvg_set_line_cap(ctx, VKVG_LINE_CAP_ROUND);
+ vkvg_move_to(ctx, x + 2 * dx, y);
+ vkvg_rel_line_to(ctx, 0, dy);
+ vkvg_rel_move_to(ctx, dx, -dy);
+ vkvg_rel_line_to(ctx, dx, dy);
+ vkvg_rel_move_to(ctx, dx, -dy / 2.f);
+ vkvg_rel_line_to(ctx, dx, 0);
+ vkvg_rel_move_to(ctx, dx, dy / 2.f);
+ vkvg_rel_line_to(ctx, dx, -dy);
+ vkvg_rel_move_to(ctx, dx, dy);
+ vkvg_rel_line_to(ctx, 0, -dy);
+ vkvg_rel_move_to(ctx, dx * 2.f, dy);
+ vkvg_rel_line_to(ctx, -dx, -dy);
+ vkvg_rel_move_to(ctx, dx * 3.f, dy / 2.f);
+ vkvg_rel_line_to(ctx, -dx, 0);
+ // vkvg_rel_line_to(ctx,0,-dy);
+ // vkvg_rel_move_to(ctx,dx,dy/2);
+ // vkvg_rel_line_to(ctx,dx,0);
+ vkvg_stroke(ctx);
- vkvg_set_line_cap(ctx,VKVG_LINE_CAP_BUTT);
- vkvg_set_line_width(ctx,1);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_move_to(ctx,x,y);
- vkvg_rel_line_to(ctx,0,dy);
- vkvg_rel_move_to(ctx,dx,-dy);
- vkvg_rel_line_to(ctx,0,dy);
- vkvg_rel_move_to(ctx,dx,-dy);
- vkvg_rel_line_to(ctx,0,dy);
- vkvg_stroke(ctx);
+ vkvg_set_line_cap(ctx, VKVG_LINE_CAP_BUTT);
+ vkvg_set_line_width(ctx, 1);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_move_to(ctx, x, y);
+ vkvg_rel_line_to(ctx, 0, dy);
+ vkvg_rel_move_to(ctx, dx, -dy);
+ vkvg_rel_line_to(ctx, 0, dy);
+ vkvg_rel_move_to(ctx, dx, -dy);
+ vkvg_rel_line_to(ctx, 0, dy);
+ vkvg_stroke(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (test, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(test, argc, argv);
+ return 0;
}
#include "test.h"
-void test(){
- VkvgContext ctx = vkvg_create(surf);
-
- float x = 250, y = 150;
-
- //vkvg_scale(ctx,2,2);
-
- vkvg_set_line_width(ctx,100);
- vkvg_set_source_rgba(ctx,0,1,0,1);
-
-
- vkvg_set_line_join(ctx,VKVG_LINE_JOIN_ROUND);
- //vkvg_rectangle(ctx,x,y,dx,dy);
-
- vkvg_move_to(ctx,x,y);
- vkvg_rel_line_to(ctx,-50,30);
- vkvg_rel_line_to(ctx,0,60);
- vkvg_rel_line_to(ctx,50,30);
- /*
- vkvg_rel_line_to(ctx,50,-30);
- vkvg_rel_line_to(ctx,50,0);
- vkvg_rel_line_to(ctx,50,30);
- vkvg_rel_line_to(ctx,0,60);
- vkvg_rel_line_to(ctx,-50,70);
- vkvg_rel_line_to(ctx,-50,0);
- vkvg_rel_line_to(ctx,-50,-70);
- vkvg_close_path(ctx);
- vkvg_stroke(ctx);
-
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_move_to(ctx,x+200,y);
- vkvg_rel_line_to(ctx,50,70);
- vkvg_rel_line_to(ctx,50,0);
- vkvg_rel_line_to(ctx,50,-70);
- vkvg_rel_line_to(ctx,0,-60);
- vkvg_rel_line_to(ctx,-50,-30);
- vkvg_rel_line_to(ctx,-50,0);
- vkvg_rel_line_to(ctx,-50,30);*/
- vkvg_close_path(ctx);
- vkvg_stroke(ctx);
-
- vkvg_set_source_rgba(ctx,0,0,1,1);
- vkvg_move_to(ctx,x+250,y);
- vkvg_rel_line_to(ctx,50,-30);
- vkvg_rel_line_to(ctx,50,0);
- vkvg_rel_line_to(ctx,50,30);
- vkvg_rel_line_to(ctx,0,60);
- vkvg_rel_line_to(ctx,-50,70);
- vkvg_rel_line_to(ctx,-50,0);
- vkvg_rel_line_to(ctx,-50,-70);
- vkvg_close_path(ctx);
- vkvg_stroke(ctx);
-
-// float dx = 150, dy = 140;
-// vkvg_rel_line_to(ctx,dx,-dy);
-// vkvg_rel_line_to(ctx,dx,dy);
-// vkvg_stroke(ctx);
-// vkvg_set_line_join(ctx,VKVG_LINE_JOIN_BEVEL);
-// vkvg_rel_move_to(ctx,-dx*2,abs(dy*1.5));
-// vkvg_rel_line_to(ctx,dx,-dy);
-// vkvg_rel_line_to(ctx,dx,dy);
-// vkvg_stroke(ctx);
-// vkvg_set_line_join(ctx,VKVG_LINE_JOIN_ROUND);
-// vkvg_rel_move_to(ctx,-dx*2,abs(dy*1.5));
-// vkvg_rel_line_to(ctx,dx,-dy);
-// vkvg_rel_line_to(ctx,dx,dy);
-// vkvg_stroke(ctx);
-// vkvg_set_line_join(ctx,VKVG_LINE_JOIN_MITER);
-
- vkvg_destroy(ctx);
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
+
+ float x = 250, y = 150;
+
+ // vkvg_scale(ctx,2,2);
+
+ vkvg_set_line_width(ctx, 100);
+ vkvg_set_source_rgba(ctx, 0, 1, 0, 1);
+
+ vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND);
+ // vkvg_rectangle(ctx,x,y,dx,dy);
+
+ vkvg_move_to(ctx, x, y);
+ vkvg_rel_line_to(ctx, -50, 30);
+ vkvg_rel_line_to(ctx, 0, 60);
+ vkvg_rel_line_to(ctx, 50, 30);
+ /*
+ vkvg_rel_line_to(ctx,50,-30);
+ vkvg_rel_line_to(ctx,50,0);
+ vkvg_rel_line_to(ctx,50,30);
+ vkvg_rel_line_to(ctx,0,60);
+ vkvg_rel_line_to(ctx,-50,70);
+ vkvg_rel_line_to(ctx,-50,0);
+ vkvg_rel_line_to(ctx,-50,-70);
+ vkvg_close_path(ctx);
+ vkvg_stroke(ctx);
+
+ vkvg_set_source_rgba(ctx,1,0,0,1);
+ vkvg_move_to(ctx,x+200,y);
+ vkvg_rel_line_to(ctx,50,70);
+ vkvg_rel_line_to(ctx,50,0);
+ vkvg_rel_line_to(ctx,50,-70);
+ vkvg_rel_line_to(ctx,0,-60);
+ vkvg_rel_line_to(ctx,-50,-30);
+ vkvg_rel_line_to(ctx,-50,0);
+ vkvg_rel_line_to(ctx,-50,30);*/
+ vkvg_close_path(ctx);
+ vkvg_stroke(ctx);
+
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 1);
+ vkvg_move_to(ctx, x + 250, y);
+ vkvg_rel_line_to(ctx, 50, -30);
+ vkvg_rel_line_to(ctx, 50, 0);
+ vkvg_rel_line_to(ctx, 50, 30);
+ vkvg_rel_line_to(ctx, 0, 60);
+ vkvg_rel_line_to(ctx, -50, 70);
+ vkvg_rel_line_to(ctx, -50, 0);
+ vkvg_rel_line_to(ctx, -50, -70);
+ vkvg_close_path(ctx);
+ vkvg_stroke(ctx);
+
+ // float dx = 150, dy = 140;
+ // vkvg_rel_line_to(ctx,dx,-dy);
+ // vkvg_rel_line_to(ctx,dx,dy);
+ // vkvg_stroke(ctx);
+ // vkvg_set_line_join(ctx,VKVG_LINE_JOIN_BEVEL);
+ // vkvg_rel_move_to(ctx,-dx*2,abs(dy*1.5));
+ // vkvg_rel_line_to(ctx,dx,-dy);
+ // vkvg_rel_line_to(ctx,dx,dy);
+ // vkvg_stroke(ctx);
+ // vkvg_set_line_join(ctx,VKVG_LINE_JOIN_ROUND);
+ // vkvg_rel_move_to(ctx,-dx*2,abs(dy*1.5));
+ // vkvg_rel_line_to(ctx,dx,-dy);
+ // vkvg_rel_line_to(ctx,dx,dy);
+ // vkvg_stroke(ctx);
+ // vkvg_set_line_join(ctx,VKVG_LINE_JOIN_MITER);
+
+ vkvg_destroy(ctx);
}
void test2() {
- VkvgContext ctx = vkvg_create(surf);
-
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_line_width(ctx, 30);
-
- vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND);
-
- //vkvg_arc (ctx, 200, 500, 100, 0, M_PI);
-
- vkvg_translate(ctx, -50, -50);
-
- vkvg_set_source_rgb(ctx, 0.5, 0, 0);
-
- for (int j = 0; j < 2; j++) {
- int i = 0;
- vkvg_move_to(ctx, 100, 100);
- for (i = 0; i < 5; i++) {
- vkvg_rel_line_to(ctx, 70, 50);
- vkvg_rel_line_to(ctx, -70, 50);
- }
- vkvg_stroke(ctx);
-
- vkvg_move_to(ctx, 200, 600);
- for (i = 0; i < 5; i++) {
- vkvg_rel_line_to(ctx, 70, -50);
- vkvg_rel_line_to(ctx, -70, -50);
- }
- vkvg_stroke(ctx);
-
- vkvg_move_to(ctx, 400, 100);
- for (i = 0; i < 5; i++) {
- vkvg_rel_line_to(ctx, -70, 50);
- vkvg_rel_line_to(ctx, 70, 50);
- }
- vkvg_stroke(ctx);
-
- vkvg_move_to(ctx, 500, 600);
- for (i = 0; i < 5; i++) {
- vkvg_rel_line_to(ctx, -70, -50);
- vkvg_rel_line_to(ctx, 70, -50);
- }
- vkvg_stroke(ctx);
- vkvg_set_line_join(ctx, VKVG_LINE_JOIN_BEVEL);
- vkvg_translate(ctx, 500, 0);
- }
-
- vkvg_destroy(ctx);
+ VkvgContext ctx = vkvg_create(surf);
+
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+ vkvg_set_line_width(ctx, 30);
+
+ vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND);
+
+ // vkvg_arc (ctx, 200, 500, 100, 0, M_PI);
+
+ vkvg_translate(ctx, -50, -50);
+
+ vkvg_set_source_rgb(ctx, 0.5, 0, 0);
+
+ for (int j = 0; j < 2; j++) {
+ int i = 0;
+ vkvg_move_to(ctx, 100, 100);
+ for (i = 0; i < 5; i++) {
+ vkvg_rel_line_to(ctx, 70, 50);
+ vkvg_rel_line_to(ctx, -70, 50);
+ }
+ vkvg_stroke(ctx);
+
+ vkvg_move_to(ctx, 200, 600);
+ for (i = 0; i < 5; i++) {
+ vkvg_rel_line_to(ctx, 70, -50);
+ vkvg_rel_line_to(ctx, -70, -50);
+ }
+ vkvg_stroke(ctx);
+
+ vkvg_move_to(ctx, 400, 100);
+ for (i = 0; i < 5; i++) {
+ vkvg_rel_line_to(ctx, -70, 50);
+ vkvg_rel_line_to(ctx, 70, 50);
+ }
+ vkvg_stroke(ctx);
+
+ vkvg_move_to(ctx, 500, 600);
+ for (i = 0; i < 5; i++) {
+ vkvg_rel_line_to(ctx, -70, -50);
+ vkvg_rel_line_to(ctx, 70, -50);
+ }
+ vkvg_stroke(ctx);
+ vkvg_set_line_join(ctx, VKVG_LINE_JOIN_BEVEL);
+ vkvg_translate(ctx, 500, 0);
+ }
+
+ vkvg_destroy(ctx);
}
void test3() {
- VkvgContext ctx = vkvg_create(surf);
-
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_line_width(ctx, 30);
-
- vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND);
-
- //vkvg_arc (ctx, 200, 500, 100, 0, M_PI);
-
- vkvg_translate(ctx, -50, -50);
-
- vkvg_set_source_rgb(ctx, 0.5, 0, 0);
-
- for (int j = 0; j < 2; j++) {
- int i = 0;
- vkvg_move_to(ctx, 100, 100);
- for (i = 0; i < 4; i++) {
- vkvg_rel_line_to(ctx, 50, 70);
- vkvg_rel_line_to(ctx, 50, -70);
- }
- vkvg_stroke(ctx);
-
- vkvg_move_to(ctx, 500, 200);
- for (i = 0; i < 4; i++) {
- vkvg_rel_line_to(ctx, -50, 70);
- vkvg_rel_line_to(ctx, -50, -70);
- }
- vkvg_stroke(ctx);
-
- vkvg_move_to(ctx, 100, 400);
- for (i = 0; i < 4; i++) {
- vkvg_rel_line_to(ctx, 50, -70);
- vkvg_rel_line_to(ctx, 50, 70);
- }
- vkvg_stroke(ctx);
-
- vkvg_move_to(ctx, 500, 500);
- for (i = 0; i < 4; i++) {
- vkvg_rel_line_to(ctx, -50, -70);
- vkvg_rel_line_to(ctx, -50, 70);
- }
- vkvg_stroke(ctx);
- vkvg_set_line_join(ctx, VKVG_LINE_JOIN_BEVEL);
- vkvg_translate(ctx, 450, 0);
- }
-
- vkvg_destroy(ctx);
+ VkvgContext ctx = vkvg_create(surf);
+
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+ vkvg_set_line_width(ctx, 30);
+
+ vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND);
+
+ // vkvg_arc (ctx, 200, 500, 100, 0, M_PI);
+
+ vkvg_translate(ctx, -50, -50);
+
+ vkvg_set_source_rgb(ctx, 0.5, 0, 0);
+
+ for (int j = 0; j < 2; j++) {
+ int i = 0;
+ vkvg_move_to(ctx, 100, 100);
+ for (i = 0; i < 4; i++) {
+ vkvg_rel_line_to(ctx, 50, 70);
+ vkvg_rel_line_to(ctx, 50, -70);
+ }
+ vkvg_stroke(ctx);
+
+ vkvg_move_to(ctx, 500, 200);
+ for (i = 0; i < 4; i++) {
+ vkvg_rel_line_to(ctx, -50, 70);
+ vkvg_rel_line_to(ctx, -50, -70);
+ }
+ vkvg_stroke(ctx);
+
+ vkvg_move_to(ctx, 100, 400);
+ for (i = 0; i < 4; i++) {
+ vkvg_rel_line_to(ctx, 50, -70);
+ vkvg_rel_line_to(ctx, 50, 70);
+ }
+ vkvg_stroke(ctx);
+
+ vkvg_move_to(ctx, 500, 500);
+ for (i = 0; i < 4; i++) {
+ vkvg_rel_line_to(ctx, -50, -70);
+ vkvg_rel_line_to(ctx, -50, 70);
+ }
+ vkvg_stroke(ctx);
+ vkvg_set_line_join(ctx, VKVG_LINE_JOIN_BEVEL);
+ vkvg_translate(ctx, 450, 0);
+ }
+
+ vkvg_destroy(ctx);
}
-
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST(test, argc, argv);
- PERFORM_TEST(test2, argc, argv);
- PERFORM_TEST(test3, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(test, argc, argv);
+ PERFORM_TEST(test2, argc, argv);
+ PERFORM_TEST(test3, argc, argv);
+ return 0;
}
#include "test.h"
void horizontal() {
- float w = (float)test_width;
- float h = (float)test_height;
-
- VkvgContext ctx = _initCtx();
-
- for (uint32_t i=0; i<test_size; i++) {
- randomize_color(ctx);
- float x1 = w*rndf();
- float y1 = h*rndf();
- float v = 500.f*rndf();
-
- vkvg_move_to (ctx, x1, y1);
- vkvg_line_to (ctx, x1 + v, y1);
- vkvg_stroke (ctx);
- }
- vkvg_destroy(ctx);
+ float w = (float)test_width;
+ float h = (float)test_height;
+
+ VkvgContext ctx = _initCtx();
+
+ for (uint32_t i = 0; i < test_size; i++) {
+ randomize_color(ctx);
+ float x1 = w * rndf();
+ float y1 = h * rndf();
+ float v = 500.f * rndf();
+
+ vkvg_move_to(ctx, x1, y1);
+ vkvg_line_to(ctx, x1 + v, y1);
+ vkvg_stroke(ctx);
+ }
+ vkvg_destroy(ctx);
}
void vertical() {
- float w = (float)test_width;
- float h = (float)test_height;
-
- VkvgContext ctx = _initCtx();
-
- for (uint32_t i=0; i<test_size; i++) {
- randomize_color(ctx);
- float x1 = w*rndf();
- float y1 = h*rndf();
- float v = 500.f*rndf();
-
- vkvg_move_to (ctx, x1, y1);
- vkvg_line_to (ctx, x1, y1 + v);
- vkvg_stroke (ctx);
- }
- vkvg_destroy(ctx);
+ float w = (float)test_width;
+ float h = (float)test_height;
+
+ VkvgContext ctx = _initCtx();
+
+ for (uint32_t i = 0; i < test_size; i++) {
+ randomize_color(ctx);
+ float x1 = w * rndf();
+ float y1 = h * rndf();
+ float v = 500.f * rndf();
+
+ vkvg_move_to(ctx, x1, y1);
+ vkvg_line_to(ctx, x1, y1 + v);
+ vkvg_stroke(ctx);
+ }
+ vkvg_destroy(ctx);
}
-void horzAndVert(){
- float w = (float)test_width;
- float h = (float)test_height;
+void horzAndVert() {
+ float w = (float)test_width;
+ float h = (float)test_height;
- VkvgContext ctx = _initCtx();
+ VkvgContext ctx = _initCtx();
- for (uint32_t i=0; i<test_size; i++) {
- randomize_color(ctx);
+ for (uint32_t i = 0; i < test_size; i++) {
+ randomize_color(ctx);
- float x1 = w*rndf();
- float y1 = h*rndf();
- float x2 = (w*rndf()) + 1;
- float y2 = (h*rndf()) + 1;
+ float x1 = w * rndf();
+ float y1 = h * rndf();
+ float x2 = (w * rndf()) + 1;
+ float y2 = (h * rndf()) + 1;
- vkvg_move_to (ctx, x1, y1);
- vkvg_line_to (ctx, x2, y2);
- vkvg_stroke (ctx);
- }
- vkvg_destroy(ctx);
+ vkvg_move_to(ctx, x1, y1);
+ vkvg_line_to(ctx, x2, y2);
+ vkvg_stroke(ctx);
+ }
+ vkvg_destroy(ctx);
}
-void multilines(){
- float w = (float)test_width;
- float h = (float)test_height;
+void multilines() {
+ float w = (float)test_width;
+ float h = (float)test_height;
- VkvgContext ctx = _initCtx();
+ VkvgContext ctx = _initCtx();
- randomize_color(ctx);
+ randomize_color(ctx);
- for (uint32_t i=0; i<test_size; i++) {
+ for (uint32_t i = 0; i < test_size; i++) {
- float x1 = w*rndf();
- float y1 = h*rndf();
- float x2 = (w*rndf()) + 1;
- float y2 = (h*rndf()) + 1;
+ float x1 = w * rndf();
+ float y1 = h * rndf();
+ float x2 = (w * rndf()) + 1;
+ float y2 = (h * rndf()) + 1;
- vkvg_move_to (ctx, x1, y1);
- vkvg_line_to (ctx, x2, y2);
- }
- vkvg_stroke (ctx);
- vkvg_destroy(ctx);
+ vkvg_move_to(ctx, x1, y1);
+ vkvg_line_to(ctx, x2, y2);
+ }
+ vkvg_stroke(ctx);
+ vkvg_destroy(ctx);
}
void multi_segments() {
- float w = (float)test_width-10;
- float h = (float)test_height-10;
+ float w = (float)test_width - 10;
+ float h = (float)test_height - 10;
VkvgContext ctx = _initCtx();
randomize_color(ctx);
- float x1 = w*rndf();
- float y1 = h*rndf();
- vkvg_move_to (ctx, x1, y1);
- for (uint32_t i=0; i<test_size; i++) {
- x1 = w*rndf();
- y1 = h*rndf();
- vkvg_line_to (ctx, x1, y1);
+ float x1 = w * rndf();
+ float y1 = h * rndf();
+ vkvg_move_to(ctx, x1, y1);
+ for (uint32_t i = 0; i < test_size; i++) {
+ x1 = w * rndf();
+ y1 = h * rndf();
+ vkvg_line_to(ctx, x1, y1);
}
- vkvg_stroke (ctx);
+ vkvg_stroke(ctx);
vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- struct timeval currentTime;
- gettimeofday(¤tTime, NULL);
+ struct timeval currentTime;
+ gettimeofday(¤tTime, NULL);
- srand((unsigned) currentTime.tv_usec);
+ srand((unsigned)currentTime.tv_usec);
PERFORM_TEST(horizontal, argc, argv);
- PERFORM_TEST(vertical, argc, argv);
- PERFORM_TEST(horzAndVert, argc, argv);
+ PERFORM_TEST(vertical, argc, argv);
+ PERFORM_TEST(horzAndVert, argc, argv);
PERFORM_TEST(multilines, argc, argv);
PERFORM_TEST(multi_segments, argc, argv);
return 0;
#define THREAD_COUNT 32
+static int finishedThreadCount = 0;
+static mtx_t *pmutex;
-static int finishedThreadCount = 0;
-static mtx_t* pmutex;
+void drawRandomRect(VkvgContext ctx, float s) {
+ float w = (float)test_width;
+ float h = (float)test_height;
+ randomize_color(ctx);
-void drawRandomRect (VkvgContext ctx, float s) {
- float w = (float)test_width;
- float h = (float)test_height;
- randomize_color(ctx);
+ float x = truncf(w * rndf());
+ float y = truncf(h * rndf());
- float x = truncf(w*rndf());
- float y = truncf(h*rndf());
-
- vkvg_rectangle(ctx, x, y, s, s);
+ vkvg_rectangle(ctx, x, y, s, s);
}
-int drawRectsThread () {
+int drawRectsThread() {
- VkvgSurface s = vkvg_surface_create(device, test_width, test_height);
- VkvgContext ctx = vkvg_create(s);
- for (uint32_t i=0; i<test_size; i++) {
- drawRandomRect(ctx, 14.0f);
- vkvg_fill (ctx);
- }
- vkvg_destroy(ctx);
+ VkvgSurface s = vkvg_surface_create(device, test_width, test_height);
+ VkvgContext ctx = vkvg_create(s);
+ for (uint32_t i = 0; i < test_size; i++) {
+ drawRandomRect(ctx, 14.0f);
+ vkvg_fill(ctx);
+ }
+ vkvg_destroy(ctx);
- mtx_lock(pmutex);
+ mtx_lock(pmutex);
- ctx = vkvg_create(surf);
- vkvg_set_source_surface (ctx, s, 0, 0);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
+ ctx = vkvg_create(surf);
+ vkvg_set_source_surface(ctx, s, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
- finishedThreadCount++;
- mtx_unlock(pmutex);
+ finishedThreadCount++;
+ mtx_unlock(pmutex);
- vkvg_surface_destroy (s);
- return 0;
+ vkvg_surface_destroy(s);
+ return 0;
}
-void fixedSizeRects(){
- mtx_t mutex;
- pmutex = &mutex;
+void fixedSizeRects() {
+ mtx_t mutex;
+ pmutex = &mutex;
- vkvg_device_set_thread_aware (device, 1);
+ vkvg_device_set_thread_aware(device, 1);
- thrd_t threads[THREAD_COUNT];
+ thrd_t threads[THREAD_COUNT];
- finishedThreadCount = 0;
- mtx_init (pmutex, mtx_plain);
- for (uint32_t i=0; i<THREAD_COUNT; i++)
- thrd_create (&threads[i], drawRectsThread, NULL);
+ finishedThreadCount = 0;
+ mtx_init(pmutex, mtx_plain);
+ for (uint32_t i = 0; i < THREAD_COUNT; i++)
+ thrd_create(&threads[i], drawRectsThread, NULL);
- const struct timespec ts = {1,0};
- while (finishedThreadCount < THREAD_COUNT)
- thrd_sleep(&ts, NULL);
+ const struct timespec ts = {1, 0};
+ while (finishedThreadCount < THREAD_COUNT)
+ thrd_sleep(&ts, NULL);
- mtx_lock(pmutex);
- mtx_unlock(pmutex);
- mtx_destroy (pmutex);
- pmutex = NULL;
+ mtx_lock(pmutex);
+ mtx_unlock(pmutex);
+ mtx_destroy(pmutex);
+ pmutex = NULL;
- vkvg_device_set_thread_aware (device, 0);
+ vkvg_device_set_thread_aware(device, 0);
}
int main(int argc, char *argv[]) {
- PERFORM_TEST (fixedSizeRects, argc, argv);
- return 0;
+ PERFORM_TEST(fixedSizeRects, argc, argv);
+ return 0;
}
#define THREAD_COUNT 32
+static int finishedThreadCount = 0;
+static mtx_t *pmutex;
-static int finishedThreadCount = 0;
-static mtx_t* pmutex;
+void drawRandomRect(VkvgContext ctx, float s) {
+ float w = (float)test_width;
+ float h = (float)test_height;
+ randomize_color(ctx);
-void drawRandomRect (VkvgContext ctx, float s) {
- float w = (float)test_width;
- float h = (float)test_height;
- randomize_color(ctx);
+ float x = truncf(w * rndf());
+ float y = truncf(h * rndf());
- float x = truncf(w*rndf());
- float y = truncf(h*rndf());
-
- vkvg_rectangle(ctx, x, y, s, s);
+ vkvg_rectangle(ctx, x, y, s, s);
}
-int drawRectsThread () {
- VkvgContext ctx = vkvg_create(surf);
- for (uint32_t i=0; i<test_size; i++) {
- drawRandomRect(ctx, 14.0f);
- vkvg_fill (ctx);
- }
- vkvg_destroy (ctx);
- mtx_lock (pmutex);
- finishedThreadCount++;
- mtx_unlock (pmutex);
- return 0;
+int drawRectsThread() {
+ VkvgContext ctx = vkvg_create(surf);
+ for (uint32_t i = 0; i < test_size; i++) {
+ drawRandomRect(ctx, 14.0f);
+ vkvg_fill(ctx);
+ }
+ vkvg_destroy(ctx);
+ mtx_lock(pmutex);
+ finishedThreadCount++;
+ mtx_unlock(pmutex);
+ return 0;
}
-void fixedSizeRects(){
- mtx_t mutex;
- pmutex = &mutex;
+void fixedSizeRects() {
+ mtx_t mutex;
+ pmutex = &mutex;
- vkvg_device_set_thread_aware (device, 1);
+ vkvg_device_set_thread_aware(device, 1);
- thrd_t threads[THREAD_COUNT];
+ thrd_t threads[THREAD_COUNT];
- finishedThreadCount = 0;
- mtx_init (pmutex, mtx_plain);
- for (uint32_t i=0; i<THREAD_COUNT; i++)
- thrd_create (&threads[i], drawRectsThread, NULL);
+ finishedThreadCount = 0;
+ mtx_init(pmutex, mtx_plain);
+ for (uint32_t i = 0; i < THREAD_COUNT; i++)
+ thrd_create(&threads[i], drawRectsThread, NULL);
- const struct timespec ts = {1,0};
- while (finishedThreadCount < THREAD_COUNT)
- thrd_sleep(&ts, NULL);
+ const struct timespec ts = {1, 0};
+ while (finishedThreadCount < THREAD_COUNT)
+ thrd_sleep(&ts, NULL);
- mtx_lock(pmutex);
- mtx_unlock(pmutex);
- mtx_destroy (pmutex);
- pmutex = NULL;
+ mtx_lock(pmutex);
+ mtx_unlock(pmutex);
+ mtx_destroy(pmutex);
+ pmutex = NULL;
- vkvg_device_set_thread_aware (device, 0);
+ vkvg_device_set_thread_aware(device, 0);
}
int main(int argc, char *argv[]) {
- PERFORM_TEST (fixedSizeRects, argc, argv);
- return 0;
+ PERFORM_TEST(fixedSizeRects, argc, argv);
+ return 0;
}
#define THREAD_COUNT 16
-
-static int finishedThreadCount = 0;
-static mtx_t* pmutex;
-
-int create_surfs () {
- for (uint32_t i=0; i<test_size; i++) {
- VkvgSurface s = vkvg_surface_create(device, test_width, test_height);
- vkvg_surface_destroy (s);
- }
-
- mtx_lock(pmutex);
- finishedThreadCount++;
- mtx_unlock(pmutex);
- return 0;
+static int finishedThreadCount = 0;
+static mtx_t *pmutex;
+
+int create_surfs() {
+ for (uint32_t i = 0; i < test_size; i++) {
+ VkvgSurface s = vkvg_surface_create(device, test_width, test_height);
+ vkvg_surface_destroy(s);
+ }
+
+ mtx_lock(pmutex);
+ finishedThreadCount++;
+ mtx_unlock(pmutex);
+ return 0;
}
-void fixedSizeRects(){
- mtx_t mutex;
- pmutex = &mutex;
+void fixedSizeRects() {
+ mtx_t mutex;
+ pmutex = &mutex;
- vkvg_device_set_thread_aware (device, 1);
+ vkvg_device_set_thread_aware(device, 1);
- thrd_t threads[THREAD_COUNT];
+ thrd_t threads[THREAD_COUNT];
- finishedThreadCount = 0;
- mtx_init (pmutex, mtx_plain);
- for (uint32_t i=0; i<THREAD_COUNT; i++)
- thrd_create (&threads[i], create_surfs, NULL);
+ finishedThreadCount = 0;
+ mtx_init(pmutex, mtx_plain);
+ for (uint32_t i = 0; i < THREAD_COUNT; i++)
+ thrd_create(&threads[i], create_surfs, NULL);
- const struct timespec ts = {1,0};
- while (finishedThreadCount < THREAD_COUNT)
- thrd_sleep(&ts, NULL);
+ const struct timespec ts = {1, 0};
+ while (finishedThreadCount < THREAD_COUNT)
+ thrd_sleep(&ts, NULL);
- mtx_lock(pmutex);
- mtx_unlock(pmutex);
- mtx_destroy (pmutex);
- pmutex = NULL;
+ mtx_lock(pmutex);
+ mtx_unlock(pmutex);
+ mtx_destroy(pmutex);
+ pmutex = NULL;
- vkvg_device_set_thread_aware (device, 0);
+ vkvg_device_set_thread_aware(device, 0);
}
int main(int argc, char *argv[]) {
- PERFORM_TEST (fixedSizeRects, argc, argv);
- return 0;
+ PERFORM_TEST(fixedSizeRects, argc, argv);
+ return 0;
}
#define THREAD_COUNT 16
-static int finishedThreadCount = 0;
-static mtx_t* pmutex;
+static int finishedThreadCount = 0;
+static mtx_t *pmutex;
-void drawRandomRect (VkvgContext ctx, float s) {
- float w = (float)test_width;
- float h = (float)test_height;
- randomize_color(ctx);
+void drawRandomRect(VkvgContext ctx, float s) {
+ float w = (float)test_width;
+ float h = (float)test_height;
+ randomize_color(ctx);
- float x = truncf(w*rndf());
- float y = truncf(h*rndf());
+ float x = truncf(w * rndf());
+ float y = truncf(h * rndf());
- vkvg_rectangle(ctx, x, y, s, s);
+ vkvg_rectangle(ctx, x, y, s, s);
}
-int _single_font_and_size () {
- VkvgSurface s = vkvg_surface_create(device, test_width, test_height);
- VkvgContext ctx = vkvg_create(s);
- vkvg_clear(ctx);
- for (uint32_t i=0; i<test_size/THREAD_COUNT; i++) {
- randomize_color(ctx);
- float x = rndf() * test_width;
- float y = rndf() * test_height;
- vkvg_select_font_face(ctx,"mono");
- vkvg_set_font_size(ctx, 20);
- vkvg_move_to(ctx,x,y);
- vkvg_show_text(ctx,"This is a test string!");
- }
- vkvg_destroy(ctx);
-
- mtx_lock(pmutex);
-
- ctx = vkvg_create(surf);
- vkvg_set_source_surface (ctx, s, 0, 0);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
-
- finishedThreadCount++;
- mtx_unlock(pmutex);
-
- vkvg_surface_destroy (s);
- return 0;
+int _single_font_and_size() {
+ VkvgSurface s = vkvg_surface_create(device, test_width, test_height);
+ VkvgContext ctx = vkvg_create(s);
+ vkvg_clear(ctx);
+ for (uint32_t i = 0; i < test_size / THREAD_COUNT; i++) {
+ randomize_color(ctx);
+ float x = rndf() * test_width;
+ float y = rndf() * test_height;
+ vkvg_select_font_face(ctx, "mono");
+ vkvg_set_font_size(ctx, 20);
+ vkvg_move_to(ctx, x, y);
+ vkvg_show_text(ctx, "This is a test string!");
+ }
+ vkvg_destroy(ctx);
+
+ mtx_lock(pmutex);
+
+ ctx = vkvg_create(surf);
+ vkvg_set_source_surface(ctx, s, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
+
+ finishedThreadCount++;
+ mtx_unlock(pmutex);
+
+ vkvg_surface_destroy(s);
+ return 0;
}
-void threaded_text(int(*testfunc)(void*)){
- mtx_t mutex;
- pmutex = &mutex;
+void threaded_text(int (*testfunc)(void *)) {
+ mtx_t mutex;
+ pmutex = &mutex;
- vkvg_device_set_thread_aware (device, 1);
+ vkvg_device_set_thread_aware(device, 1);
- thrd_t threads[THREAD_COUNT];
+ thrd_t threads[THREAD_COUNT];
- finishedThreadCount = 0;
- mtx_init (pmutex, mtx_plain);
- for (uint32_t i=0; i<THREAD_COUNT; i++)
- thrd_create (&threads[i], testfunc, NULL);
+ finishedThreadCount = 0;
+ mtx_init(pmutex, mtx_plain);
+ for (uint32_t i = 0; i < THREAD_COUNT; i++)
+ thrd_create(&threads[i], testfunc, NULL);
- const struct timespec ts = {1,0};
- while (finishedThreadCount < THREAD_COUNT)
- thrd_sleep(&ts, NULL);
+ const struct timespec ts = {1, 0};
+ while (finishedThreadCount < THREAD_COUNT)
+ thrd_sleep(&ts, NULL);
- mtx_lock(pmutex);
- mtx_unlock(pmutex);
- mtx_destroy (pmutex);
- pmutex = NULL;
+ mtx_lock(pmutex);
+ mtx_unlock(pmutex);
+ mtx_destroy(pmutex);
+ pmutex = NULL;
- vkvg_device_set_thread_aware (device, 0);
-}
-void single_font_and_size() {
- threaded_text (_single_font_and_size);
+ vkvg_device_set_thread_aware(device, 0);
}
+void single_font_and_size() { threaded_text(_single_font_and_size); }
int main(int argc, char *argv[]) {
- PERFORM_TEST (single_font_and_size, argc, argv);
- return 0;
+ PERFORM_TEST(single_font_and_size, argc, argv);
+ return 0;
}
#include "vkvg.h"
int main(int argc, char *argv[]) {
- vkvg_device_create_info_t info = {
- VK_SAMPLE_COUNT_1_BIT, false
- };
- VkvgDevice dev = vkvg_device_create(&info);
- VkvgSurface surf = vkvg_surface_create(dev, 512,512);
- VkvgContext ctx = vkvg_create(surf);
+ vkvg_device_create_info_t info = {VK_SAMPLE_COUNT_1_BIT, false};
+ VkvgDevice dev = vkvg_device_create(&info);
+ VkvgSurface surf = vkvg_surface_create(dev, 512, 512);
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
- vkvg_rectangle(ctx, 10, 10, 250, 200);
- vkvg_set_source_rgb(ctx, 1, 0, 0);
- vkvg_fill(ctx);
+ vkvg_clear(ctx);
+ vkvg_rectangle(ctx, 10, 10, 250, 200);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_fill(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
- vkvg_surface_write_to_png(surf, "offscreen.png");
- vkvg_surface_destroy(surf);
+ vkvg_surface_write_to_png(surf, "offscreen.png");
+ vkvg_surface_destroy(surf);
- vkvg_device_destroy(dev);
- return 0;
+ vkvg_device_destroy(dev);
+ return 0;
}
float lineWidth = 10.f;
-VkvgSurface createSurf (uint32_t width, uint32_t height) {
- VkvgSurface s = vkvg_surface_create(device, width, height);
- VkvgContext ctx = vkvg_create (s);
- vkvg_set_line_width(ctx,lineWidth);
- float hlw = lineWidth/2.f;
- /*
- vkvg_set_source_rgba(ctx,0,1,0,0.5);
- vkvg_fill_preserve(ctx);*/
- vkvg_set_source_rgba(ctx,1,0,0,0.5);
- vkvg_paint(ctx);
- vkvg_set_source_rgba(ctx,0,0,1,0.5);
- vkvg_rectangle(ctx,hlw,hlw,(float)width-lineWidth,(float)height-lineWidth);
- vkvg_stroke(ctx);
- vkvg_destroy(ctx);
- return s;
+VkvgSurface createSurf(uint32_t width, uint32_t height) {
+ VkvgSurface s = vkvg_surface_create(device, width, height);
+ VkvgContext ctx = vkvg_create(s);
+ vkvg_set_line_width(ctx, lineWidth);
+ float hlw = lineWidth / 2.f;
+ /*
+ vkvg_set_source_rgba(ctx,0,1,0,0.5);
+ vkvg_fill_preserve(ctx);*/
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.5);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 0.5);
+ vkvg_rectangle(ctx, hlw, hlw, (float)width - lineWidth, (float)height - lineWidth);
+ vkvg_stroke(ctx);
+ vkvg_destroy(ctx);
+ return s;
}
-void paint(){
- VkvgSurface src = createSurf(256,256);
- VkvgContext ctx = _initCtx(surf);
- vkvg_set_source_surface(ctx, src, 0, 0);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
- vkvg_surface_destroy(src);
+void paint() {
+ VkvgSurface src = createSurf(256, 256);
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_set_source_surface(ctx, src, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
+ vkvg_surface_destroy(src);
}
-void paint_with_offset(){
- VkvgSurface src = createSurf(256,256);
- VkvgContext ctx = _initCtx(surf);
- vkvg_set_source_rgba(ctx,0,1,0,0.5);
- vkvg_paint(ctx);
- vkvg_set_source_surface(ctx, src, 100, 100);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
- vkvg_surface_destroy(src);
+void paint_with_offset() {
+ VkvgSurface src = createSurf(256, 256);
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_set_source_rgba(ctx, 0, 1, 0, 0.5);
+ vkvg_paint(ctx);
+ vkvg_set_source_surface(ctx, src, 100, 100);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
+ vkvg_surface_destroy(src);
}
-void paint_multiple(){
- VkvgSurface src = createSurf(256,256);
- VkvgContext ctx = _initCtx(surf);
- for(int i=0;i<10;i++) {
- vkvg_set_source_surface(ctx, src, i * 20, i * 20);
- vkvg_paint(ctx);
- }
- vkvg_destroy(ctx);
- vkvg_surface_destroy(src);
+void paint_multiple() {
+ VkvgSurface src = createSurf(256, 256);
+ VkvgContext ctx = _initCtx(surf);
+ for (int i = 0; i < 10; i++) {
+ vkvg_set_source_surface(ctx, src, i * 20, i * 20);
+ vkvg_paint(ctx);
+ }
+ vkvg_destroy(ctx);
+ vkvg_surface_destroy(src);
}
-void paint_with_rotation(){
- VkvgSurface src = createSurf(256,256);
- VkvgContext ctx = _initCtx(surf);
- vkvg_set_source_surface(ctx, src, 0, 0);
- vkvg_rotate(ctx, 45);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
- vkvg_surface_destroy(src);
+void paint_with_rotation() {
+ VkvgSurface src = createSurf(256, 256);
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_set_source_surface(ctx, src, 0, 0);
+ vkvg_rotate(ctx, 45);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
+ vkvg_surface_destroy(src);
}
-void paint_with_scale(){
- VkvgSurface src = createSurf(256,256);
- VkvgContext ctx = _initCtx(surf);
- vkvg_set_source_surface(ctx, src, 0, 0);
- vkvg_scale (ctx, 0.2f,0.2f);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
- vkvg_surface_destroy(src);
+void paint_with_scale() {
+ VkvgSurface src = createSurf(256, 256);
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_set_source_surface(ctx, src, 0, 0);
+ vkvg_scale(ctx, 0.2f, 0.2f);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
+ vkvg_surface_destroy(src);
}
-void paint_rect(){
- VkvgSurface src = createSurf(256,256);
- VkvgContext ctx = _initCtx(surf);
- vkvg_set_source_surface(ctx, src, 0, 0);
- vkvg_rectangle(ctx,100,100,300,200);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
- vkvg_surface_destroy(src);
+void paint_rect() {
+ VkvgSurface src = createSurf(256, 256);
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_set_source_surface(ctx, src, 0, 0);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
+ vkvg_surface_destroy(src);
}
-//TODO:test failed: full screen paint instead of rotated rect
-void paint_rect_with_rotation(){
- VkvgContext ctx = _initCtx(surf);
- vkvg_rotate(ctx, 45);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_rectangle(ctx,100,100,300,200);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
+// TODO:test failed: full screen paint instead of rotated rect
+void paint_rect_with_rotation() {
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_rotate(ctx, 45);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
}
-void paint_rect_with_scale(){
- VkvgContext ctx = _initCtx(surf);
- vkvg_scale (ctx, 0.2f,0.2f);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_rectangle(ctx,100,100,300,200);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
+void paint_rect_with_scale() {
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_scale(ctx, 0.2f, 0.2f);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (paint, argc, argv);
- PERFORM_TEST (paint_with_offset, argc, argv);
- PERFORM_TEST (paint_multiple, argc, argv);
- PERFORM_TEST (paint_with_rotation, argc, argv);
- PERFORM_TEST (paint_with_scale, argc, argv);
- PERFORM_TEST (paint_rect, argc, argv);
- PERFORM_TEST (paint_rect_with_rotation, argc, argv);
- PERFORM_TEST (paint_rect_with_scale, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(paint, argc, argv);
+ PERFORM_TEST(paint_with_offset, argc, argv);
+ PERFORM_TEST(paint_multiple, argc, argv);
+ PERFORM_TEST(paint_with_rotation, argc, argv);
+ PERFORM_TEST(paint_with_scale, argc, argv);
+ PERFORM_TEST(paint_rect, argc, argv);
+ PERFORM_TEST(paint_rect_with_rotation, argc, argv);
+ PERFORM_TEST(paint_rect_with_scale, argc, argv);
+ return 0;
}
#include "test.h"
#include "vectors.h"
-vkvg_fill_rule_t fillrule = VKVG_FILL_RULE_NON_ZERO;
-static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
-float lineWidth = 4.0f;
-vkvg_line_join_t lineJoin = VKVG_LINE_JOIN_MITER;
-vkvg_line_cap_t lineCap = VKVG_LINE_CAP_BUTT;
-bool isClosed = false, refresh = true;
-bool startWithArc = false, endWithArc = false;
-
-int ptsCount = 0;
-vec2 pts[1024];
-int hoverPt = -1;
+vkvg_fill_rule_t fillrule = VKVG_FILL_RULE_NON_ZERO;
+static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
+float lineWidth = 4.0f;
+vkvg_line_join_t lineJoin = VKVG_LINE_JOIN_MITER;
+vkvg_line_cap_t lineCap = VKVG_LINE_CAP_BUTT;
+bool isClosed = false, refresh = true;
+bool startWithArc = false, endWithArc = false;
+
+int ptsCount = 0;
+vec2 pts[1024];
+int hoverPt = -1;
double pointSize = 7;
-float _dashes[] = {5.0f,3.0f};
-int _ndashes = 2;
-
-void emit_path (VkvgContext ctx) {
- vkvg_move_to(ctx,pts[0].x,pts[0].y);
- for (int i=1; i<ptsCount; i++)
- vkvg_line_to(ctx,pts[i].x,pts[i].y);
- if (isClosed)
- vkvg_close_path(ctx);
+float _dashes[] = {5.0f, 3.0f};
+int _ndashes = 2;
+
+void emit_path(VkvgContext ctx) {
+ vkvg_move_to(ctx, pts[0].x, pts[0].y);
+ for (int i = 1; i < ptsCount; i++)
+ vkvg_line_to(ctx, pts[i].x, pts[i].y);
+ if (isClosed)
+ vkvg_close_path(ctx);
}
-void draw (){
- refresh = false;
-
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_set_line_width (ctx,lineWidth);
- vkvg_set_line_join (ctx, lineJoin);
- vkvg_set_line_cap (ctx, lineCap);
-
- emit_path(ctx);
- float x1, y1, x2, y2;
- vkvg_path_extents(ctx, &x1, &y1, &x2, &y2);
- vkvg_set_source_rgba(ctx,0.2,0.2,1,0.5);
- if (hoverPt>=0) {
- if (isClosed)
- vkvg_fill_preserve(ctx);
- vkvg_set_source_rgba(ctx,1,0.2,0.2,0.5);
- vkvg_stroke_preserve(ctx);
- vkvg_set_dash(ctx, NULL, 0, 0);
- vkvg_set_line_width(ctx,1);
- vkvg_set_source_rgba(ctx,0,0,0,1);
- vkvg_stroke(ctx);
- vkvg_set_source_rgba(ctx,0.5f,0.5f,1.0f,0.7f);
- vkvg_arc (ctx, pts[hoverPt].x, pts[hoverPt].y, pointSize, 0, M_PIF*2);
- vkvg_fill_preserve(ctx);
- vkvg_stroke(ctx);
- } else {
- if (isClosed)
- vkvg_fill_preserve(ctx);
- vkvg_set_source_rgba(ctx,1,0.2,0.2,0.5);
- vkvg_stroke(ctx);
- }
-
- vkvg_rectangle(ctx, x1, y1, x2 - x1, y2 - y1);
- vkvg_set_dash(ctx, _dashes, _ndashes, 0);
- vkvg_set_line_width(ctx,1);
- vkvg_set_source_rgba(ctx,0,1,0,1);
- vkvg_stroke(ctx);
-
- vkvg_destroy(ctx);
+void draw() {
+ refresh = false;
+
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_set_line_width(ctx, lineWidth);
+ vkvg_set_line_join(ctx, lineJoin);
+ vkvg_set_line_cap(ctx, lineCap);
+
+ emit_path(ctx);
+ float x1, y1, x2, y2;
+ vkvg_path_extents(ctx, &x1, &y1, &x2, &y2);
+ vkvg_set_source_rgba(ctx, 0.2, 0.2, 1, 0.5);
+ if (hoverPt >= 0) {
+ if (isClosed)
+ vkvg_fill_preserve(ctx);
+ vkvg_set_source_rgba(ctx, 1, 0.2, 0.2, 0.5);
+ vkvg_stroke_preserve(ctx);
+ vkvg_set_dash(ctx, NULL, 0, 0);
+ vkvg_set_line_width(ctx, 1);
+ vkvg_set_source_rgba(ctx, 0, 0, 0, 1);
+ vkvg_stroke(ctx);
+ vkvg_set_source_rgba(ctx, 0.5f, 0.5f, 1.0f, 0.7f);
+ vkvg_arc(ctx, pts[hoverPt].x, pts[hoverPt].y, pointSize, 0, M_PIF * 2);
+ vkvg_fill_preserve(ctx);
+ vkvg_stroke(ctx);
+ } else {
+ if (isClosed)
+ vkvg_fill_preserve(ctx);
+ vkvg_set_source_rgba(ctx, 1, 0.2, 0.2, 0.5);
+ vkvg_stroke(ctx);
+ }
+
+ vkvg_rectangle(ctx, x1, y1, x2 - x1, y2 - y1);
+ vkvg_set_dash(ctx, _dashes, _ndashes, 0);
+ vkvg_set_line_width(ctx, 1);
+ vkvg_set_source_rgba(ctx, 0, 1, 0, 1);
+ vkvg_stroke(ctx);
+
+ vkvg_destroy(ctx);
}
-static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
- if (action != GLFW_PRESS)
- return;
- switch (key) {
- case GLFW_KEY_ESCAPE :
- glfwSetWindowShouldClose(window, GLFW_TRUE);
- break;
- case GLFW_KEY_W :
- isClosed ^= true;
- break;
- case GLFW_KEY_DELETE :
- ptsCount = 0;
- break;
- case GLFW_KEY_J :
- lineJoin++;
- if (lineJoin > 2)
- lineJoin = 0;
- break;
- case GLFW_KEY_C :
- lineCap++;
- if (lineCap > 2)
- lineCap = 0;
- break;
- case GLFW_KEY_KP_SUBTRACT :
- if (ptsCount > 1)
- ptsCount--;
- break;
- }
- refresh = true;
+static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+ if (action != GLFW_PRESS)
+ return;
+ switch (key) {
+ case GLFW_KEY_ESCAPE:
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+ break;
+ case GLFW_KEY_W:
+ isClosed ^= true;
+ break;
+ case GLFW_KEY_DELETE:
+ ptsCount = 0;
+ break;
+ case GLFW_KEY_J:
+ lineJoin++;
+ if (lineJoin > 2)
+ lineJoin = 0;
+ break;
+ case GLFW_KEY_C:
+ lineCap++;
+ if (lineCap > 2)
+ lineCap = 0;
+ break;
+ case GLFW_KEY_KP_SUBTRACT:
+ if (ptsCount > 1)
+ ptsCount--;
+ break;
+ }
+ refresh = true;
}
static vec2 mousePos;
-static void mouse_move_callback(GLFWwindow* window, double x, double y){
- mousePos = (vec2) {x, y};
- if (mouseDown) {
- if (hoverPt < 0)
- return;
- pts[hoverPt] = mousePos;
- refresh = true;
- } else {
- for (int i=0; i<ptsCount; i++) {
- if (x > pts[i].x - pointSize &&
- x < pts[i].x + pointSize &&
- y > pts[i].y - pointSize &&
- y < pts[i].y + pointSize) {
- hoverPt = i;
- refresh = true;
- return;
- }
- }
- refresh = true;
- hoverPt = -1;
- }
+static void mouse_move_callback(GLFWwindow *window, double x, double y) {
+ mousePos = (vec2){x, y};
+ if (mouseDown) {
+ if (hoverPt < 0)
+ return;
+ pts[hoverPt] = mousePos;
+ refresh = true;
+ } else {
+ for (int i = 0; i < ptsCount; i++) {
+ if (x > pts[i].x - pointSize && x < pts[i].x + pointSize && y > pts[i].y - pointSize &&
+ y < pts[i].y + pointSize) {
+ hoverPt = i;
+ refresh = true;
+ return;
+ }
+ }
+ refresh = true;
+ hoverPt = -1;
+ }
}
-static void scroll_callback(GLFWwindow* window, double x, double y){
- if (y<0.f)
- zoom *= 0.5f;
- else
- zoom *= 2.0f;
+static void scroll_callback(GLFWwindow *window, double x, double y) {
+ if (y < 0.f)
+ zoom *= 0.5f;
+ else
+ zoom *= 2.0f;
}
-static void mouse_button_callback(GLFWwindow* window, int but, int state, int modif){
- if (but != GLFW_MOUSE_BUTTON_1)
- return;
- if (state == GLFW_TRUE)
- mouseDown = true;
- else
- mouseDown = false;
- if (state == GLFW_TRUE && hoverPt < 0)
- pts[ptsCount++] = mousePos;
- refresh = true;
+static void mouse_button_callback(GLFWwindow *window, int but, int state, int modif) {
+ if (but != GLFW_MOUSE_BUTTON_1)
+ return;
+ if (state == GLFW_TRUE)
+ mouseDown = true;
+ else
+ mouseDown = false;
+ if (state == GLFW_TRUE && hoverPt < 0)
+ pts[ptsCount++] = mousePos;
+ refresh = true;
}
+int main(int argc, char *argv[]) {
+ _parse_args(argc, argv);
+ VkEngine e;
+ e = vkengine_create(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
-int main(int argc, char* argv[]) {
+ VkhPresenter r = e->renderer;
+ vkengine_set_key_callback(e, key_callback);
+ vkengine_set_mouse_but_callback(e, mouse_button_callback);
+ vkengine_set_cursor_pos_callback(e, mouse_move_callback);
+ vkengine_set_scroll_callback(e, scroll_callback);
- _parse_args (argc, argv);
- VkEngine e;
- e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
+ vkvg_device_create_info_t info = {samples, false, vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0};
+ device = vkvg_device_create(&info);
+ surf = vkvg_surface_create(device, test_width, test_height);
- VkhPresenter r = e->renderer;
- vkengine_set_key_callback (e, key_callback);
- vkengine_set_mouse_but_callback(e, mouse_button_callback);
- vkengine_set_cursor_pos_callback(e, mouse_move_callback);
- vkengine_set_scroll_callback(e, scroll_callback);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
- vkvg_device_create_info_t info = {
- samples,
- false,
- vkh_app_get_inst(e->app),
- r->dev->phy,
- r->dev->dev,
- r->qFam,
- 0
- };
- device = vkvg_device_create(&info);
- surf = vkvg_surface_create(device, test_width, test_height);
+ while (!vkengine_should_close(e)) {
+ glfwPollEvents();
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ if (refresh)
+ draw();
- while (!vkengine_should_close (e)) {
- glfwPollEvents();
+ if (!vkh_presenter_draw(r)) {
+ vkh_presenter_get_size(r, &test_width, &test_height);
+ vkvg_surface_destroy(surf);
+ surf = vkvg_surface_create(device, test_width, test_height);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ vkDeviceWaitIdle(r->dev->dev);
+ continue;
+ }
+ }
+ vkDeviceWaitIdle(e->dev->dev);
- if (refresh)
- draw ();
+ vkvg_surface_destroy(surf);
- if (!vkh_presenter_draw (r)){
- vkh_presenter_get_size (r, &test_width, &test_height);
- vkvg_surface_destroy (surf);
- surf = vkvg_surface_create(device, test_width, test_height);
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
- vkDeviceWaitIdle(r->dev->dev);
- continue;
- }
- }
- vkDeviceWaitIdle(e->dev->dev);
+ vkvg_device_destroy(device);
- vkvg_surface_destroy (surf);
+ vkengine_destroy(e);
- vkvg_device_destroy (device);
-
- vkengine_destroy (e);
-
- return 0;
+ return 0;
}
#include "test.h"
-float lineWidth = 10.f;
-const char* imgPath = "data/miroir.jpg";
-
-VkvgPattern create_grad (VkvgContext ctx) {
- VkvgPattern pat = vkvg_pattern_create_linear(0,0,200,0);
- vkvg_pattern_add_color_stop(pat, 0, 1, 0, 0, 1);
- vkvg_pattern_add_color_stop(pat, 0.5, 0, 1, 0, 1);
- vkvg_pattern_add_color_stop(pat, 1.0, 0, 0, 1, 1);
- return pat;
+float lineWidth = 10.f;
+const char *imgPath = "data/miroir.jpg";
+
+VkvgPattern create_grad(VkvgContext ctx) {
+ VkvgPattern pat = vkvg_pattern_create_linear(0, 0, 200, 0);
+ vkvg_pattern_add_color_stop(pat, 0, 1, 0, 0, 1);
+ vkvg_pattern_add_color_stop(pat, 0.5, 0, 1, 0, 1);
+ vkvg_pattern_add_color_stop(pat, 1.0, 0, 0, 1, 1);
+ return pat;
}
-VkvgSurface createSurf (uint32_t width, uint32_t height) {
- VkvgSurface s = vkvg_surface_create(device, width, height);
- VkvgContext ctx = _initCtx(surf);
- vkvg_set_line_width(ctx,lineWidth);
- float hlw = lineWidth/2.f;
- /*
- vkvg_set_source_rgba(ctx,0,1,0,0.5);
- vkvg_fill_preserve(ctx);*/
- vkvg_set_source_rgba(ctx,1,0,0,0.5);
- vkvg_paint(ctx);
- vkvg_set_source_rgba(ctx,0,0,1,0.5);
- vkvg_rectangle(ctx,hlw,hlw,(float)width-lineWidth,(float)height-lineWidth);
- vkvg_stroke(ctx);
- vkvg_destroy(ctx);
- return s;
+VkvgSurface createSurf(uint32_t width, uint32_t height) {
+ VkvgSurface s = vkvg_surface_create(device, width, height);
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_set_line_width(ctx, lineWidth);
+ float hlw = lineWidth / 2.f;
+ /*
+ vkvg_set_source_rgba(ctx,0,1,0,0.5);
+ vkvg_fill_preserve(ctx);*/
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.5);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 0.5);
+ vkvg_rectangle(ctx, hlw, hlw, (float)width - lineWidth, (float)height - lineWidth);
+ vkvg_stroke(ctx);
+ vkvg_destroy(ctx);
+ return s;
}
void img_scale() {
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
- VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
- VkvgContext ctx = _initCtx(surf);
-
- vkvg_translate(ctx, 100,100);
-
- vkvg_matrix_t mat;
- vkvg_matrix_init_scale(&mat, 2.0, 2.0);
- vkvg_pattern_set_matrix (pat, &mat);
-
- vkvg_set_source (ctx, pat);
- vkvg_rectangle(ctx, 0 , 0, 200, 140);
- vkvg_fill(ctx);
- vkvg_destroy(ctx);
- vkvg_pattern_destroy(pat);
- vkvg_surface_destroy(imgSurf);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
+ VkvgContext ctx = _initCtx(surf);
+
+ vkvg_translate(ctx, 100, 100);
+
+ vkvg_matrix_t mat;
+ vkvg_matrix_init_scale(&mat, 2.0, 2.0);
+ vkvg_pattern_set_matrix(pat, &mat);
+
+ vkvg_set_source(ctx, pat);
+ vkvg_rectangle(ctx, 0, 0, 200, 140);
+ vkvg_fill(ctx);
+ vkvg_destroy(ctx);
+ vkvg_pattern_destroy(pat);
+ vkvg_surface_destroy(imgSurf);
}
-void pat_scale(){
+void pat_scale() {
- VkvgContext ctx = _initCtx(surf);
- VkvgPattern pat = create_grad(ctx);
+ VkvgContext ctx = _initCtx(surf);
+ VkvgPattern pat = create_grad(ctx);
- vkvg_translate(ctx, 100,100);
+ vkvg_translate(ctx, 100, 100);
- vkvg_matrix_t mat;
- vkvg_matrix_init_scale(&mat, 0.5, 0.5);
- vkvg_pattern_set_matrix (pat, &mat);
+ vkvg_matrix_t mat;
+ vkvg_matrix_init_scale(&mat, 0.5, 0.5);
+ vkvg_pattern_set_matrix(pat, &mat);
- vkvg_set_source (ctx, pat);
- vkvg_rectangle(ctx, 0 , 0, 200, 140);
- vkvg_fill(ctx);
- vkvg_destroy(ctx);
- vkvg_pattern_destroy(pat);
+ vkvg_set_source(ctx, pat);
+ vkvg_rectangle(ctx, 0, 0, 200, 140);
+ vkvg_fill(ctx);
+ vkvg_destroy(ctx);
+ vkvg_pattern_destroy(pat);
}
static float angle = 0;
-void pat_rotate(){
- angle += 0.001f;
+void pat_rotate() {
+ angle += 0.001f;
- VkvgContext ctx = _initCtx(surf);
- VkvgPattern pat = create_grad(ctx);
+ VkvgContext ctx = _initCtx(surf);
+ VkvgPattern pat = create_grad(ctx);
- //vkvg_translate(ctx, 100,100);
+ // vkvg_translate(ctx, 100,100);
- vkvg_matrix_t mat;
- vkvg_matrix_init_translate(&mat, 100, 70);
- vkvg_matrix_rotate(&mat, angle);
- vkvg_pattern_set_matrix (pat, &mat);
+ vkvg_matrix_t mat;
+ vkvg_matrix_init_translate(&mat, 100, 70);
+ vkvg_matrix_rotate(&mat, angle);
+ vkvg_pattern_set_matrix(pat, &mat);
- vkvg_set_source (ctx, pat);
- vkvg_rectangle(ctx, 0 , 0, 200, 140);
- vkvg_fill(ctx);
- vkvg_destroy(ctx);
- vkvg_pattern_destroy(pat);
+ vkvg_set_source(ctx, pat);
+ vkvg_rectangle(ctx, 0, 0, 200, 140);
+ vkvg_fill(ctx);
+ vkvg_destroy(ctx);
+ vkvg_pattern_destroy(pat);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (pat_scale, argc, argv);
- PERFORM_TEST (pat_rotate, argc, argv);
- PERFORM_TEST (img_scale, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(pat_scale, argc, argv);
+ PERFORM_TEST(pat_rotate, argc, argv);
+ PERFORM_TEST(img_scale, argc, argv);
+ return 0;
}
#include "test.h"
-void drawRandomRect (VkvgContext ctx, float s) {
- float w = (float)test_width;
- float h = (float)test_height;
- randomize_color(ctx);
+void drawRandomRect(VkvgContext ctx, float s) {
+ float w = (float)test_width;
+ float h = (float)test_height;
+ randomize_color(ctx);
- float x = truncf(w*rndf());
- float y = truncf(h*rndf());
+ float x = truncf(w * rndf());
+ float y = truncf(h * rndf());
- vkvg_rectangle(ctx, x, y, s, s);
+ vkvg_rectangle(ctx, x, y, s, s);
}
-void fixedSizeRects(){
- VkvgContext ctx = _initCtx ();
- for (uint32_t i=0; i<test_size; i++) {
- drawRandomRect(ctx, 50.0f);
- vkvg_fill (ctx);
- }
- vkvg_destroy(ctx);
+void fixedSizeRects() {
+ VkvgContext ctx = _initCtx();
+ for (uint32_t i = 0; i < test_size; i++) {
+ drawRandomRect(ctx, 50.0f);
+ vkvg_fill(ctx);
+ }
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- PERFORM_TEST (fixedSizeRects, argc, argv);
- return 0;
+ PERFORM_TEST(fixedSizeRects, argc, argv);
+ return 0;
}
#include "test.h"
/*void drawRandomRect (VkvgContext ctx) {
- float w = (float)test_width;
- float h = (float)test_height;
- randomize_color(ctx);
+ float w = (float)test_width;
+ float h = (float)test_height;
+ randomize_color(ctx);
- float z = truncf((0.5f*w*rand()/RAND_MAX)+1.f);
- float v = truncf((0.5f*w*rand()/RAND_MAX)+1.f);
- float x = truncf((w-z)*rand()/RAND_MAX);
- float y = truncf((h-v)*rand()/RAND_MAX);
+ float z = truncf((0.5f*w*rand()/RAND_MAX)+1.f);
+ float v = truncf((0.5f*w*rand()/RAND_MAX)+1.f);
+ float x = truncf((w-z)*rand()/RAND_MAX);
+ float y = truncf((h-v)*rand()/RAND_MAX);
- vkvg_rectangle(ctx, x, y, z, v);
+ vkvg_rectangle(ctx, x, y, z, v);
}*/
static float shape_size = 0.2f;
-void _shape_fill(shape_t shape){
- VkvgContext ctx = _initCtx ();
- for (uint32_t i=0; i<test_size; i++) {
- draw_random_shape(ctx, shape, shape_size);
- vkvg_fill(ctx);
- }
- vkvg_destroy(ctx);
-}
-void _shape_stroke(shape_t shape){
- VkvgContext ctx = _initCtx ();
- for (uint32_t i=0; i<test_size; i++) {
- draw_random_shape(ctx, shape, shape_size);
- vkvg_stroke (ctx);
- }
- vkvg_destroy(ctx);
-}
-void _shape_fill_stroke(shape_t shape){
- VkvgContext ctx = _initCtx ();
+void _shape_fill(shape_t shape) {
+ VkvgContext ctx = _initCtx();
+ for (uint32_t i = 0; i < test_size; i++) {
+ draw_random_shape(ctx, shape, shape_size);
+ vkvg_fill(ctx);
+ }
+ vkvg_destroy(ctx);
+}
+void _shape_stroke(shape_t shape) {
+ VkvgContext ctx = _initCtx();
+ for (uint32_t i = 0; i < test_size; i++) {
+ draw_random_shape(ctx, shape, shape_size);
+ vkvg_stroke(ctx);
+ }
+ vkvg_destroy(ctx);
+}
+void _shape_fill_stroke(shape_t shape) {
+ VkvgContext ctx = _initCtx();
- for (uint32_t i=0; i<test_size; i++) {
- draw_random_shape(ctx, shape, shape_size);
- vkvg_fill_preserve(ctx);
- vkvg_stroke(ctx);
- }
- vkvg_destroy(ctx);
+ for (uint32_t i = 0; i < test_size; i++) {
+ draw_random_shape(ctx, shape, shape_size);
+ vkvg_fill_preserve(ctx);
+ vkvg_stroke(ctx);
+ }
+ vkvg_destroy(ctx);
}
-void rectangles_fill () {
- _shape_fill(SHAPE_RECTANGLE);
-}
-void rectangles_stroke () {
- _shape_stroke(SHAPE_RECTANGLE);
-}
-void rectangles_fill_stroke () {
- _shape_fill_stroke(SHAPE_RECTANGLE);
-}
-void rounded_rects_fill () {
- _shape_fill(SHAPE_ROUNDED_RECTANGLE);
-}
-void rounded_rects_stroke () {
- _shape_stroke(SHAPE_ROUNDED_RECTANGLE);
-}
-void rounded_rects_fill_stroke () {
- _shape_fill_stroke(SHAPE_ROUNDED_RECTANGLE);
-}
-void circles_fill () {
- _shape_fill(SHAPE_CIRCLE);
-}
-void circles_stroke () {
- _shape_stroke(SHAPE_CIRCLE);
-}
-void circles_fill_stroke () {
- _shape_fill_stroke(SHAPE_CIRCLE);
-}
-void stars_fill () {
- _shape_fill(SHAPE_STAR);
-}
-void stars_stroke () {
- _shape_stroke(SHAPE_STAR);
-}
-void stars_fill_stroke () {
- _shape_fill_stroke(SHAPE_STAR);
-}
-void random_fill () {
- _shape_fill(SHAPE_RANDOM);
-}
-void random_stroke () {
- _shape_stroke(SHAPE_RANDOM);
-}
-void random_fill_stroke () {
- _shape_fill_stroke(SHAPE_RANDOM);
-}
+void rectangles_fill() { _shape_fill(SHAPE_RECTANGLE); }
+void rectangles_stroke() { _shape_stroke(SHAPE_RECTANGLE); }
+void rectangles_fill_stroke() { _shape_fill_stroke(SHAPE_RECTANGLE); }
+void rounded_rects_fill() { _shape_fill(SHAPE_ROUNDED_RECTANGLE); }
+void rounded_rects_stroke() { _shape_stroke(SHAPE_ROUNDED_RECTANGLE); }
+void rounded_rects_fill_stroke() { _shape_fill_stroke(SHAPE_ROUNDED_RECTANGLE); }
+void circles_fill() { _shape_fill(SHAPE_CIRCLE); }
+void circles_stroke() { _shape_stroke(SHAPE_CIRCLE); }
+void circles_fill_stroke() { _shape_fill_stroke(SHAPE_CIRCLE); }
+void stars_fill() { _shape_fill(SHAPE_STAR); }
+void stars_stroke() { _shape_stroke(SHAPE_STAR); }
+void stars_fill_stroke() { _shape_fill_stroke(SHAPE_STAR); }
+void random_fill() { _shape_fill(SHAPE_RANDOM); }
+void random_stroke() { _shape_stroke(SHAPE_RANDOM); }
+void random_fill_stroke() { _shape_fill_stroke(SHAPE_RANDOM); }
int main(int argc, char *argv[]) {
- PERFORM_TEST (rectangles_fill, argc, argv);
- PERFORM_TEST (rectangles_stroke, argc, argv);
- PERFORM_TEST (rectangles_fill_stroke, argc, argv);
+ PERFORM_TEST(rectangles_fill, argc, argv);
+ PERFORM_TEST(rectangles_stroke, argc, argv);
+ PERFORM_TEST(rectangles_fill_stroke, argc, argv);
- PERFORM_TEST (rounded_rects_fill, argc, argv);
- PERFORM_TEST (rounded_rects_stroke, argc, argv);
- PERFORM_TEST (rounded_rects_fill_stroke, argc, argv);
+ PERFORM_TEST(rounded_rects_fill, argc, argv);
+ PERFORM_TEST(rounded_rects_stroke, argc, argv);
+ PERFORM_TEST(rounded_rects_fill_stroke, argc, argv);
- PERFORM_TEST (circles_fill, argc, argv);
- PERFORM_TEST (circles_stroke, argc, argv);
- PERFORM_TEST (circles_fill_stroke, argc, argv);
+ PERFORM_TEST(circles_fill, argc, argv);
+ PERFORM_TEST(circles_stroke, argc, argv);
+ PERFORM_TEST(circles_fill_stroke, argc, argv);
- PERFORM_TEST (stars_fill, argc, argv);
- PERFORM_TEST (stars_stroke, argc, argv);
- PERFORM_TEST (stars_fill_stroke, argc, argv);
+ PERFORM_TEST(stars_fill, argc, argv);
+ PERFORM_TEST(stars_stroke, argc, argv);
+ PERFORM_TEST(stars_fill_stroke, argc, argv);
- PERFORM_TEST (random_fill, argc, argv);
- PERFORM_TEST (random_stroke, argc, argv);
- PERFORM_TEST (random_fill_stroke, argc, argv);
+ PERFORM_TEST(random_fill, argc, argv);
+ PERFORM_TEST(random_stroke, argc, argv);
+ PERFORM_TEST(random_fill_stroke, argc, argv);
- return 0;
+ return 0;
}
#include "test.h"
-void test(){
- VkvgContext ctx = vkvg_create(surf);
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
- VkvgPattern radial = vkvg_pattern_create_radial (250.0f,250.0f,0,300,300,260.0f);
- vkvg_pattern_add_color_stop(radial, 0.0,1,0,0,1);
- vkvg_pattern_add_color_stop(radial, 0.5,0,1,0,1);
- vkvg_pattern_add_color_stop(radial, 1.0,0,0,0,1);
- vkvg_set_source(ctx, radial);
- vkvg_paint(ctx);
- vkvg_pattern_destroy(radial);
+ VkvgPattern radial = vkvg_pattern_create_radial(250.0f, 250.0f, 0, 300, 300, 260.0f);
+ vkvg_pattern_add_color_stop(radial, 0.0, 1, 0, 0, 1);
+ vkvg_pattern_add_color_stop(radial, 0.5, 0, 1, 0, 1);
+ vkvg_pattern_add_color_stop(radial, 1.0, 0, 0, 0, 1);
+ vkvg_set_source(ctx, radial);
+ vkvg_paint(ctx);
+ vkvg_pattern_destroy(radial);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (test, argc, argv);
+ no_test_size = true;
+ PERFORM_TEST(test, argc, argv);
- return 0;
+ return 0;
}
#include "test.h"
#if VKVG_RECORDING
-void test(){
- VkvgContext ctx = _initCtx(surf);
-
- vkvg_scale(ctx,0.5,0.5);
- vkvg_start_recording(ctx);
-
- vkvg_set_source_rgba(ctx,0.1f,0.9f,0.1f,1.0f);
- vkvg_move_to(ctx,100,100);
- vkvg_rel_line_to(ctx,50,200);
- vkvg_rel_line_to(ctx,150,-100);
- vkvg_rel_line_to(ctx,100,200);
- vkvg_rel_line_to(ctx,-100,100);
- vkvg_rel_line_to(ctx,-10,-100);
- vkvg_rel_line_to(ctx,-190,-50);
- vkvg_rel_line_to(ctx,300,50);
- vkvg_rel_line_to(ctx,50,0);
- vkvg_rel_line_to(ctx,0, 50);
- vkvg_rel_line_to(ctx,50,0);
- vkvg_rel_line_to(ctx,0, 50);
- vkvg_rel_line_to(ctx,50,0);
- vkvg_rel_line_to(ctx,0, 50);
- vkvg_rel_line_to(ctx,50,0);
- vkvg_rel_line_to(ctx,0, 50);
- vkvg_close_path(ctx);
-
- vkvg_stroke_preserve(ctx);
- vkvg_fill(ctx);
-
- VkvgRecording rec = vkvg_stop_recording(ctx);
-
- vkvg_translate(ctx,400,0);
- vkvg_replay(ctx, rec);
-
- vkvg_destroy(ctx);
- vkvg_recording_destroy(rec);
+void test() {
+ VkvgContext ctx = _initCtx(surf);
+
+ vkvg_scale(ctx, 0.5, 0.5);
+ vkvg_start_recording(ctx);
+
+ vkvg_set_source_rgba(ctx, 0.1f, 0.9f, 0.1f, 1.0f);
+ vkvg_move_to(ctx, 100, 100);
+ vkvg_rel_line_to(ctx, 50, 200);
+ vkvg_rel_line_to(ctx, 150, -100);
+ vkvg_rel_line_to(ctx, 100, 200);
+ vkvg_rel_line_to(ctx, -100, 100);
+ vkvg_rel_line_to(ctx, -10, -100);
+ vkvg_rel_line_to(ctx, -190, -50);
+ vkvg_rel_line_to(ctx, 300, 50);
+ vkvg_rel_line_to(ctx, 50, 0);
+ vkvg_rel_line_to(ctx, 0, 50);
+ vkvg_rel_line_to(ctx, 50, 0);
+ vkvg_rel_line_to(ctx, 0, 50);
+ vkvg_rel_line_to(ctx, 50, 0);
+ vkvg_rel_line_to(ctx, 0, 50);
+ vkvg_rel_line_to(ctx, 50, 0);
+ vkvg_rel_line_to(ctx, 0, 50);
+ vkvg_close_path(ctx);
+
+ vkvg_stroke_preserve(ctx);
+ vkvg_fill(ctx);
+
+ VkvgRecording rec = vkvg_stop_recording(ctx);
+
+ vkvg_translate(ctx, 400, 0);
+ vkvg_replay(ctx, rec);
+
+ vkvg_destroy(ctx);
+ vkvg_recording_destroy(rec);
}
#endif
int main(int argc, char *argv[]) {
- no_test_size = true;
+ no_test_size = true;
#if VKVG_RECORDING
- PERFORM_TEST (test, argc, argv);
+ PERFORM_TEST(test, argc, argv);
#endif
- return 0;
+ return 0;
}
-
#include "test.h"
void draw(VkvgContext ctx) {
- vkvg_set_source_rgba(ctx,0,0,1,0.5);
- vkvg_rectangle(ctx,100,100,200,200);
- vkvg_fill(ctx);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 0.5);
+ vkvg_rectangle(ctx, 100, 100, 200, 200);
+ vkvg_fill(ctx);
- vkvg_rectangle(ctx,200,200,200,200);
- vkvg_set_source_rgba(ctx,1,0,0,0.5);
- vkvg_fill(ctx);
+ vkvg_rectangle(ctx, 200, 200, 200, 200);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.5);
+ vkvg_fill(ctx);
}
-void test(){
+void test() {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
- draw(ctx);
+ draw(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
-void test_evenodd(){
+void test_evenodd() {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- draw(ctx);
+ draw(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (test, argc, argv);
- PERFORM_TEST (test_evenodd, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(test, argc, argv);
+ PERFORM_TEST(test_evenodd, argc, argv);
+ return 0;
}
#include "test.h"
void recurse_draw(VkvgContext ctx, int depth) {
- depth++;
- vkvg_save(ctx);
+ depth++;
+ vkvg_save(ctx);
- vkvg_translate (ctx, 5,5);
- vkvg_rectangle(ctx, (float)depth,(float)depth,200,200);
- /*vkvg_clip_preserve(ctx);
- vkvg_set_source_rgb(ctx, 1.f/depth, 1.f / depth, 1.f / depth);
- vkvg_fill_preserve(ctx);*/
- vkvg_set_source_rgb(ctx, 0,1,0);
- vkvg_stroke(ctx);
+ vkvg_translate(ctx, 5, 5);
+ vkvg_rectangle(ctx, (float)depth, (float)depth, 200, 200);
+ /*vkvg_clip_preserve(ctx);
+ vkvg_set_source_rgb(ctx, 1.f/depth, 1.f / depth, 1.f / depth);
+ vkvg_fill_preserve(ctx);*/
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_stroke(ctx);
- if (depth < 20)
- recurse_draw (ctx, depth);
+ if (depth < 20)
+ recurse_draw(ctx, depth);
- vkvg_restore(ctx);
+ vkvg_restore(ctx);
}
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
-void test(){
- VkvgContext ctx = vkvg_create(surf);
+ recurse_draw(ctx, 0);
- recurse_draw(ctx, 0);
-
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (test, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(test, argc, argv);
+ return 0;
}
#include "test.h"
-void paint(){
- VkvgContext ctx = _initCtx(surf);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
+void paint() {
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
}
-void paint_with_rotation(){
- VkvgContext ctx = _initCtx(surf);
- vkvg_rotate(ctx, 45);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
+void paint_with_rotation() {
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_rotate(ctx, 45);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
}
-void paint_with_scale(){
- VkvgContext ctx = _initCtx(surf);
- vkvg_scale (ctx, 0.2f,0.2f);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
+void paint_with_scale() {
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_scale(ctx, 0.2f, 0.2f);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
}
-void paint_rect(){
- VkvgContext ctx = _initCtx(surf);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_rectangle(ctx,100,100,300,200);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
+void paint_rect() {
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
}
-//TODO:test failed: full screen paint instead of rotated rect
-void paint_rect_with_rotation(){
- VkvgContext ctx = _initCtx(surf);
- vkvg_rotate(ctx, 45);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_rectangle(ctx,100,100,300,200);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
+// TODO:test failed: full screen paint instead of rotated rect
+void paint_rect_with_rotation() {
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_rotate(ctx, 45);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
}
-void paint_rect_with_scale(){
- VkvgContext ctx = _initCtx(surf);
- vkvg_scale (ctx, 0.2f,0.2f);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_rectangle(ctx,100,100,300,200);
- vkvg_paint(ctx);
- vkvg_destroy(ctx);
+void paint_rect_with_scale() {
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_scale(ctx, 0.2f, 0.2f);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_rectangle(ctx, 100, 100, 300, 200);
+ vkvg_paint(ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (paint, argc, argv);
- PERFORM_TEST (paint_with_rotation, argc, argv);
- PERFORM_TEST (paint_with_scale, argc, argv);
- PERFORM_TEST (paint_rect, argc, argv);
- PERFORM_TEST (paint_rect_with_rotation, argc, argv);
- PERFORM_TEST (paint_rect_with_scale, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(paint, argc, argv);
+ PERFORM_TEST(paint_with_rotation, argc, argv);
+ PERFORM_TEST(paint_with_scale, argc, argv);
+ PERFORM_TEST(paint_rect, argc, argv);
+ PERFORM_TEST(paint_rect_with_rotation, argc, argv);
+ PERFORM_TEST(paint_rect_with_scale, argc, argv);
+ return 0;
}
#include "test.h"
-void test(){
- VkvgContext ctx = vkvg_create(surf);
-
- vkvg_set_line_width(ctx, 1);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_move_to(ctx,200.5f,200.5f);
- vkvg_line_to(ctx,400.5f,200.5f);
- vkvg_line_to(ctx,400.5f,400.5f);
- vkvg_line_to(ctx,200.5f,400.5f);
- vkvg_close_path(ctx);
- vkvg_stroke(ctx);
-
- vkvg_set_source_rgba(ctx,0,1,0,1);
- vkvg_move_to(ctx,300.5f,300.5f);
- vkvg_line_to(ctx,500.5f,300.5f);
- vkvg_line_to(ctx,500.5f,500.5f);
- vkvg_line_to(ctx,300.5f,500.5f);
- vkvg_stroke(ctx);
-
- //vkvg_set_source_rgba(ctx,0,0.2,0.35,1);
- //vkvg_fill(ctx);
-
- vkvg_set_source_rgba(ctx,0.5f,1,0,1);
- vkvg_move_to(ctx,320.5f,320.5f);
- vkvg_line_to(ctx,520.5f,320.5f);
- vkvg_line_to(ctx,520.5f,520.5f);
- vkvg_line_to(ctx,320.5f,520.5f);
- //vkvg_close_path(ctx);
- vkvg_stroke(ctx);
- vkvg_set_line_width(ctx, 40);
- vkvg_set_source_rgba(ctx,0.5f,0.6f,1,1.0f);
- vkvg_move_to(ctx,700,475);
- vkvg_line_to(ctx,400,475);
- vkvg_stroke(ctx);
- vkvg_set_source_rgba(ctx,0,0.5f,0.5f,0.5f);
- vkvg_move_to(ctx,300,200);
- vkvg_arc(ctx, 200,200,100,0, M_PIF);
- vkvg_stroke(ctx);
-
- vkvg_set_line_width(ctx, 20);
- vkvg_set_source_rgba(ctx,0.1f,0.1f,0.1f,0.5f);
- vkvg_move_to(ctx,100,60);
- vkvg_line_to(ctx,400,600);
- vkvg_stroke(ctx);
-
- vkvg_set_source_rgba(ctx,1,1,1,1);
- vkvg_set_line_width(ctx, 1);
- vkvg_rectangle(ctx,600.5f,200.5f,100,60);
- vkvg_stroke(ctx);
-
- vkvg_destroy(ctx);
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
+
+ vkvg_set_line_width(ctx, 1);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_move_to(ctx, 200.5f, 200.5f);
+ vkvg_line_to(ctx, 400.5f, 200.5f);
+ vkvg_line_to(ctx, 400.5f, 400.5f);
+ vkvg_line_to(ctx, 200.5f, 400.5f);
+ vkvg_close_path(ctx);
+ vkvg_stroke(ctx);
+
+ vkvg_set_source_rgba(ctx, 0, 1, 0, 1);
+ vkvg_move_to(ctx, 300.5f, 300.5f);
+ vkvg_line_to(ctx, 500.5f, 300.5f);
+ vkvg_line_to(ctx, 500.5f, 500.5f);
+ vkvg_line_to(ctx, 300.5f, 500.5f);
+ vkvg_stroke(ctx);
+
+ // vkvg_set_source_rgba(ctx,0,0.2,0.35,1);
+ // vkvg_fill(ctx);
+
+ vkvg_set_source_rgba(ctx, 0.5f, 1, 0, 1);
+ vkvg_move_to(ctx, 320.5f, 320.5f);
+ vkvg_line_to(ctx, 520.5f, 320.5f);
+ vkvg_line_to(ctx, 520.5f, 520.5f);
+ vkvg_line_to(ctx, 320.5f, 520.5f);
+ // vkvg_close_path(ctx);
+ vkvg_stroke(ctx);
+ vkvg_set_line_width(ctx, 40);
+ vkvg_set_source_rgba(ctx, 0.5f, 0.6f, 1, 1.0f);
+ vkvg_move_to(ctx, 700, 475);
+ vkvg_line_to(ctx, 400, 475);
+ vkvg_stroke(ctx);
+ vkvg_set_source_rgba(ctx, 0, 0.5f, 0.5f, 0.5f);
+ vkvg_move_to(ctx, 300, 200);
+ vkvg_arc(ctx, 200, 200, 100, 0, M_PIF);
+ vkvg_stroke(ctx);
+
+ vkvg_set_line_width(ctx, 20);
+ vkvg_set_source_rgba(ctx, 0.1f, 0.1f, 0.1f, 0.5f);
+ vkvg_move_to(ctx, 100, 60);
+ vkvg_line_to(ctx, 400, 600);
+ vkvg_stroke(ctx);
+
+ vkvg_set_source_rgba(ctx, 1, 1, 1, 1);
+ vkvg_set_line_width(ctx, 1);
+ vkvg_rectangle(ctx, 600.5f, 200.5f, 100, 60);
+ vkvg_stroke(ctx);
+
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (test, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(test, argc, argv);
+ return 0;
}
#include "test.h"
-void create_destroy_multi_512(){
- VkvgSurface* surfs = (VkvgSurface*)malloc(sizeof(VkvgSurface)*test_size);
- for (uint32_t i = 0; i < test_size; i++)
- surfs[i] = vkvg_surface_create (device, 512, 512);
- for (uint32_t i = 0; i < test_size; i++)
- vkvg_surface_destroy(surfs[i]);
- free(surfs);
+void create_destroy_multi_512() {
+ VkvgSurface *surfs = (VkvgSurface *)malloc(sizeof(VkvgSurface) * test_size);
+ for (uint32_t i = 0; i < test_size; i++)
+ surfs[i] = vkvg_surface_create(device, 512, 512);
+ for (uint32_t i = 0; i < test_size; i++)
+ vkvg_surface_destroy(surfs[i]);
+ free(surfs);
}
-void create_destroy_single_512(){
- VkvgSurface s = vkvg_surface_create (device, 512, 512);
- vkvg_surface_destroy (s);
+void create_destroy_single_512() {
+ VkvgSurface s = vkvg_surface_create(device, 512, 512);
+ vkvg_surface_destroy(s);
}
int main(int argc, char *argv[]) {
- PERFORM_TEST (create_destroy_multi_512, argc, argv);
- no_test_size = true;
- PERFORM_TEST (create_destroy_single_512, argc, argv);
- return 0;
+ PERFORM_TEST(create_destroy_multi_512, argc, argv);
+ no_test_size = true;
+ PERFORM_TEST(create_destroy_single_512, argc, argv);
+ return 0;
}
#include "vkvg-svg.h"
-static float rotation = 0.f;
-static const char* path = "data/tiger.svg";
-static const char* svgSubPath = "data/checkbox.svg";
-
+static float rotation = 0.f;
+static const char *path = "data/tiger.svg";
+static const char *svgSubPath = "data/checkbox.svg";
void svg_surface() {
- VkvgSurface svgSurf = vkvg_surface_create_from_svg (device, test_width, test_height, path);
+ VkvgSurface svgSurf = vkvg_surface_create_from_svg(device, test_width, test_height, path);
- VkvgContext ctx = _initCtx(surf);
+ VkvgContext ctx = _initCtx(surf);
- vkvg_set_source_rgb(ctx,1,1,1);
- vkvg_paint(ctx);
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
+ vkvg_paint(ctx);
- vkvg_set_source_surface(ctx, svgSurf, 0,0);
- vkvg_paint(ctx);
+ vkvg_set_source_surface(ctx, svgSurf, 0, 0);
+ vkvg_paint(ctx);
- vkvg_destroy(ctx);
- vkvg_surface_destroy(svgSurf);
+ vkvg_destroy(ctx);
+ vkvg_surface_destroy(svgSurf);
}
-void vkvg_svg () {
- VkvgSvg svg = vkvg_svg_load (path);
- uint32_t w, h;
- vkvg_svg_get_dimensions(svg, &w, &h);
- VkvgContext ctx = _initCtx(surf);
- vkvg_clear(ctx);
+void vkvg_svg() {
+ VkvgSvg svg = vkvg_svg_load(path);
+ uint32_t w, h;
+ vkvg_svg_get_dimensions(svg, &w, &h);
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_clear(ctx);
- vkvg_svg_render (svg, ctx, NULL);
+ vkvg_svg_render(svg, ctx, NULL);
- vkvg_destroy(ctx);
- vkvg_svg_destroy (svg);
+ vkvg_destroy(ctx);
+ vkvg_svg_destroy(svg);
}
-void vkvg_svg_sub () {
- VkvgSvg svg = vkvg_svg_load (svgSubPath);
- uint32_t w, h;
- vkvg_svg_get_dimensions(svg, &w, &h);
- VkvgContext ctx = _initCtx(surf);
- vkvg_clear(ctx);
-
- vkvg_svg_render (svg, ctx, "#True");
- vkvg_translate(ctx, 200, 0);
- vkvg_svg_render (svg, ctx, "#False");
-
- vkvg_destroy(ctx);
- vkvg_svg_destroy (svg);
+void vkvg_svg_sub() {
+ VkvgSvg svg = vkvg_svg_load(svgSubPath);
+ uint32_t w, h;
+ vkvg_svg_get_dimensions(svg, &w, &h);
+ VkvgContext ctx = _initCtx(surf);
+ vkvg_clear(ctx);
+
+ vkvg_svg_render(svg, ctx, "#True");
+ vkvg_translate(ctx, 200, 0);
+ vkvg_svg_render(svg, ctx, "#False");
+
+ vkvg_destroy(ctx);
+ vkvg_svg_destroy(svg);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
+ no_test_size = true;
- PERFORM_TEST (svg_surface, argc, argv);
- PERFORM_TEST (vkvg_svg, argc, argv);
- PERFORM_TEST (vkvg_svg_sub, argc, argv);
- return 0;
+ PERFORM_TEST(svg_surface, argc, argv);
+ PERFORM_TEST(vkvg_svg, argc, argv);
+ PERFORM_TEST(vkvg_svg_sub, argc, argv);
+ return 0;
}
#include "test.h"
-void cairo_test_fill_rule (VkvgContext cr){
- vkvg_set_line_width (cr, 6);
-
- //vkvg_scale(cr,3,3);
- vkvg_set_source_rgba(cr,1,0,0,1);
- vkvg_move_to(cr,50,150);
- vkvg_rel_line_to(cr,50,70);
- vkvg_rel_line_to(cr,50,0);
- vkvg_rel_line_to(cr,50,-70);
- vkvg_rel_line_to(cr,0,-60);
- vkvg_rel_line_to(cr,-50,-30);
- vkvg_rel_line_to(cr,-50,0);
- vkvg_rel_line_to(cr,-50,30);
- vkvg_close_path(cr);
-
-
-// vkvg_set_line_join(cr,VKVG_LINE_JOIN_ROUND);
- vkvg_set_source_rgb (cr, 0, 0.7f, 0);
- vkvg_rectangle (cr, 12, 12, 232, 70);
- //vkvg_stroke (cr);
-// vkvg_new_sub_path (cr);
- vkvg_arc (cr, 64, 64, 40, 0, M_PIF*2.f);
- //vkvg_close_path(cr);
-
- vkvg_new_sub_path (cr);
- vkvg_arc_negative (cr, 192, 64, 40, M_PIF*2.f, 0);
- //vkvg_close_path(cr);
-
- //vkvg_rectangle (cr, 30, 30, 20, 200);
- //vkvg_rectangle (cr, 130, 30, 20, 200);
- //vkvg_set_fill_rule (cr, vkvg_FILL_RULE_EVEN_ODD);
-
- vkvg_fill_preserve(cr);
-
- vkvg_set_source_rgb (cr, 0, 0, 0);
- vkvg_stroke (cr);
+void cairo_test_fill_rule(VkvgContext cr) {
+ vkvg_set_line_width(cr, 6);
+
+ // vkvg_scale(cr,3,3);
+ vkvg_set_source_rgba(cr, 1, 0, 0, 1);
+ vkvg_move_to(cr, 50, 150);
+ vkvg_rel_line_to(cr, 50, 70);
+ vkvg_rel_line_to(cr, 50, 0);
+ vkvg_rel_line_to(cr, 50, -70);
+ vkvg_rel_line_to(cr, 0, -60);
+ vkvg_rel_line_to(cr, -50, -30);
+ vkvg_rel_line_to(cr, -50, 0);
+ vkvg_rel_line_to(cr, -50, 30);
+ vkvg_close_path(cr);
+
+ // vkvg_set_line_join(cr,VKVG_LINE_JOIN_ROUND);
+ vkvg_set_source_rgb(cr, 0, 0.7f, 0);
+ vkvg_rectangle(cr, 12, 12, 232, 70);
+ // vkvg_stroke (cr);
+ // vkvg_new_sub_path (cr);
+ vkvg_arc(cr, 64, 64, 40, 0, M_PIF * 2.f);
+ // vkvg_close_path(cr);
+
+ vkvg_new_sub_path(cr);
+ vkvg_arc_negative(cr, 192, 64, 40, M_PIF * 2.f, 0);
+ // vkvg_close_path(cr);
+
+ // vkvg_rectangle (cr, 30, 30, 20, 200);
+ // vkvg_rectangle (cr, 130, 30, 20, 200);
+ // vkvg_set_fill_rule (cr, vkvg_FILL_RULE_EVEN_ODD);
+
+ vkvg_fill_preserve(cr);
+
+ vkvg_set_source_rgb(cr, 0, 0, 0);
+ vkvg_stroke(cr);
}
-void cairo_test_text (VkvgContext cr) {
- vkvg_text_extents_t extents;
- vkvg_font_extents_t ft;
-
- //vkvg_set_fill_rule(cr, VKVG_FILL_RULE_NON_ZERO);
- const char *utf8 = "vkvg|Ãp";
- float x,y;
-
- //vkvg_select_font_face (cr, "times");
- vkvg_select_font_face (cr, "linux biolinum keyboard");
- vkvg_set_font_size (cr, 50);
- vkvg_font_extents(cr, &ft);
- vkvg_text_extents (cr, utf8, &extents);
- vkvg_set_source_rgb(cr,0,0,0);
-
- x=25.0f;
- y=150.0f;
-
- vkvg_move_to (cr, x,y);
- vkvg_show_text (cr, utf8);
-
- /* draw helping lines */
- vkvg_set_source_rgba (cr, 0, 0.2f, 0.2f, 0.6f);
- vkvg_set_line_width (cr, 1.0f);
- vkvg_new_path(cr);
- vkvg_arc (cr, x, y, 10.0f, 0, 2.f*M_PIF);
- vkvg_fill (cr);
- vkvg_move_to (cr, x,y);
- //vkvg_rel_line_to (cr, 0, -30);
- vkvg_rel_line_to (cr, 0, -ft.ascent);
- vkvg_rel_line_to (cr, extents.width, 0);
- vkvg_rel_line_to (cr, extents.x_bearing, -extents.y_bearing);
-
- vkvg_stroke (cr);
-
- vkvg_move_to (cr, x,y);
- vkvg_rel_line_to (cr, extents.width, 0);
- vkvg_set_source_rgba (cr, 0.0, 0.0, 0.9f, 0.6f);
-
- vkvg_stroke (cr);
-
- vkvg_move_to (cr, x,y);
- vkvg_rel_line_to (cr, 0, ft.descent);
- vkvg_rel_line_to (cr, extents.width, 0);
- vkvg_set_source_rgba (cr, 0.9f, 0.0, 0.0, 0.6f);
-
- vkvg_stroke (cr);
-
- vkvg_move_to (cr, x-10,y-ft.ascent);
- vkvg_rel_line_to (cr, 0, ft.height);
- vkvg_set_source_rgba (cr, 0.0, 0.1f, 0.0, 0.6f);
-
- vkvg_stroke (cr);
+void cairo_test_text(VkvgContext cr) {
+ vkvg_text_extents_t extents;
+ vkvg_font_extents_t ft;
+
+ // vkvg_set_fill_rule(cr, VKVG_FILL_RULE_NON_ZERO);
+ const char *utf8 = "vkvg|Ãp";
+ float x, y;
+
+ // vkvg_select_font_face (cr, "times");
+ vkvg_select_font_face(cr, "linux biolinum keyboard");
+ vkvg_set_font_size(cr, 50);
+ vkvg_font_extents(cr, &ft);
+ vkvg_text_extents(cr, utf8, &extents);
+ vkvg_set_source_rgb(cr, 0, 0, 0);
+
+ x = 25.0f;
+ y = 150.0f;
+
+ vkvg_move_to(cr, x, y);
+ vkvg_show_text(cr, utf8);
+
+ /* draw helping lines */
+ vkvg_set_source_rgba(cr, 0, 0.2f, 0.2f, 0.6f);
+ vkvg_set_line_width(cr, 1.0f);
+ vkvg_new_path(cr);
+ vkvg_arc(cr, x, y, 10.0f, 0, 2.f * M_PIF);
+ vkvg_fill(cr);
+ vkvg_move_to(cr, x, y);
+ // vkvg_rel_line_to (cr, 0, -30);
+ vkvg_rel_line_to(cr, 0, -ft.ascent);
+ vkvg_rel_line_to(cr, extents.width, 0);
+ vkvg_rel_line_to(cr, extents.x_bearing, -extents.y_bearing);
+
+ vkvg_stroke(cr);
+
+ vkvg_move_to(cr, x, y);
+ vkvg_rel_line_to(cr, extents.width, 0);
+ vkvg_set_source_rgba(cr, 0.0, 0.0, 0.9f, 0.6f);
+
+ vkvg_stroke(cr);
+
+ vkvg_move_to(cr, x, y);
+ vkvg_rel_line_to(cr, 0, ft.descent);
+ vkvg_rel_line_to(cr, extents.width, 0);
+ vkvg_set_source_rgba(cr, 0.9f, 0.0, 0.0, 0.6f);
+
+ vkvg_stroke(cr);
+
+ vkvg_move_to(cr, x - 10, y - ft.ascent);
+ vkvg_rel_line_to(cr, 0, ft.height);
+ vkvg_set_source_rgba(cr, 0.0, 0.1f, 0.0, 0.6f);
+
+ vkvg_stroke(cr);
}
-void cairo_test_clip (VkvgContext cr){
- vkvg_arc (cr, 128.0f, 128.0f, 76.8f, 0, 2.f * M_PIF);
- vkvg_clip (cr);
- //vkvg_new_path (cr); /* current path is not
- // consumed by vkvg_clip() */
- vkvg_set_source_rgba(cr, 0, 0, 0, 1);
- vkvg_rectangle (cr, 0, 0, 256, 256);
- vkvg_fill (cr);
- vkvg_set_source_rgba (cr, 0, 1, 0, 1);
- vkvg_move_to (cr, -100, -100);
- vkvg_line_to (cr, 256, 256);
- vkvg_move_to (cr, 356, -100);
- vkvg_line_to (cr, 0, 256);
- vkvg_set_line_width (cr, 10.0f);
- vkvg_stroke (cr);
+void cairo_test_clip(VkvgContext cr) {
+ vkvg_arc(cr, 128.0f, 128.0f, 76.8f, 0, 2.f * M_PIF);
+ vkvg_clip(cr);
+ // vkvg_new_path (cr); /* current path is not
+ // consumed by vkvg_clip() */
+ vkvg_set_source_rgba(cr, 0, 0, 0, 1);
+ vkvg_rectangle(cr, 0, 0, 256, 256);
+ vkvg_fill(cr);
+ vkvg_set_source_rgba(cr, 0, 1, 0, 1);
+ vkvg_move_to(cr, -100, -100);
+ vkvg_line_to(cr, 256, 256);
+ vkvg_move_to(cr, 356, -100);
+ vkvg_line_to(cr, 0, 256);
+ vkvg_set_line_width(cr, 10.0f);
+ vkvg_stroke(cr);
}
-void cairo_test_curves (VkvgContext cr){
- float x=25.6f, y=128.0f;
- float x1=102.4f, y1=230.4f,
- x2=153.6f, y2=25.6f,
- x3=230.4f, y3=128.0f;
-
- vkvg_set_source_rgb (cr, 0, 0, 0);
- vkvg_move_to (cr, x, y);
- vkvg_curve_to (cr, x1, y1, x2, y2, x3, y3);
-
- vkvg_set_line_width (cr, 10.0f);
- vkvg_stroke (cr);
-
- vkvg_set_source_rgba (cr, 1, 0.2f, 0.2f, 0.6f);
- vkvg_set_line_width (cr, 6.0f);
- vkvg_move_to (cr,x,y); vkvg_line_to (cr,x1,y1);
- vkvg_move_to (cr,x2,y2); vkvg_line_to (cr,x3,y3);
- vkvg_stroke (cr);
+void cairo_test_curves(VkvgContext cr) {
+ float x = 25.6f, y = 128.0f;
+ float x1 = 102.4f, y1 = 230.4f, x2 = 153.6f, y2 = 25.6f, x3 = 230.4f, y3 = 128.0f;
+
+ vkvg_set_source_rgb(cr, 0, 0, 0);
+ vkvg_move_to(cr, x, y);
+ vkvg_curve_to(cr, x1, y1, x2, y2, x3, y3);
+
+ vkvg_set_line_width(cr, 10.0f);
+ vkvg_stroke(cr);
+
+ vkvg_set_source_rgba(cr, 1, 0.2f, 0.2f, 0.6f);
+ vkvg_set_line_width(cr, 6.0f);
+ vkvg_move_to(cr, x, y);
+ vkvg_line_to(cr, x1, y1);
+ vkvg_move_to(cr, x2, y2);
+ vkvg_line_to(cr, x3, y3);
+ vkvg_stroke(cr);
}
-void cairo_test_rounded_rect (VkvgContext cr) {
- /* a custom shape that could be wrapped in a function */
- float x0 = 25.6f, /* parameters like vkvg_rectangle */
- y0 = 25.6f,
- rect_width = 204.8f,
- rect_height = 204.8f,
- radius = 102.4f; /* and an approximate curvature radius */
-
- float x1,y1;
-
- x1=x0+rect_width;
- y1=y0+rect_height;
- if (!rect_width || !rect_height)
- return;
- if (rect_width/2<radius) {
- if (rect_height/2<radius) {
- vkvg_move_to (cr, x0, (y0 + y1)/2);
- vkvg_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
- vkvg_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
- vkvg_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
- vkvg_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
- } else {
- vkvg_move_to (cr, x0, y0 + radius);
- vkvg_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
- vkvg_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
- vkvg_line_to (cr, x1 , y1 - radius);
- vkvg_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
- vkvg_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
- }
- } else {
- if (rect_height/2<radius) {
- vkvg_move_to (cr, x0, (y0 + y1)/2);
- vkvg_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
- vkvg_line_to (cr, x1 - radius, y0);
- vkvg_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
- vkvg_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
- vkvg_line_to (cr, x0 + radius, y1);
- vkvg_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
- } else {
- vkvg_move_to (cr, x0, y0 + radius);
- vkvg_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
- vkvg_line_to (cr, x1 - radius, y0);
- vkvg_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
- vkvg_line_to (cr, x1 , y1 - radius);
- vkvg_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
- vkvg_line_to (cr, x0 + radius, y1);
- vkvg_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
- }
- }
- vkvg_close_path (cr);
-
- vkvg_set_source_rgb (cr, 0.5f, 0.5f, 1);
- vkvg_fill_preserve (cr);
- vkvg_set_source_rgba (cr, 0.5f, 0, 0, 0.5f);
- vkvg_set_line_width (cr, 10.0f);
- vkvg_stroke (cr);
+void cairo_test_rounded_rect(VkvgContext cr) {
+ /* a custom shape that could be wrapped in a function */
+ float x0 = 25.6f, /* parameters like vkvg_rectangle */
+ y0 = 25.6f, rect_width = 204.8f, rect_height = 204.8f,
+ radius = 102.4f; /* and an approximate curvature radius */
+
+ float x1, y1;
+
+ x1 = x0 + rect_width;
+ y1 = y0 + rect_height;
+ if (!rect_width || !rect_height)
+ return;
+ if (rect_width / 2 < radius) {
+ if (rect_height / 2 < radius) {
+ vkvg_move_to(cr, x0, (y0 + y1) / 2);
+ vkvg_curve_to(cr, x0, y0, x0, y0, (x0 + x1) / 2, y0);
+ vkvg_curve_to(cr, x1, y0, x1, y0, x1, (y0 + y1) / 2);
+ vkvg_curve_to(cr, x1, y1, x1, y1, (x1 + x0) / 2, y1);
+ vkvg_curve_to(cr, x0, y1, x0, y1, x0, (y0 + y1) / 2);
+ } else {
+ vkvg_move_to(cr, x0, y0 + radius);
+ vkvg_curve_to(cr, x0, y0, x0, y0, (x0 + x1) / 2, y0);
+ vkvg_curve_to(cr, x1, y0, x1, y0, x1, y0 + radius);
+ vkvg_line_to(cr, x1, y1 - radius);
+ vkvg_curve_to(cr, x1, y1, x1, y1, (x1 + x0) / 2, y1);
+ vkvg_curve_to(cr, x0, y1, x0, y1, x0, y1 - radius);
+ }
+ } else {
+ if (rect_height / 2 < radius) {
+ vkvg_move_to(cr, x0, (y0 + y1) / 2);
+ vkvg_curve_to(cr, x0, y0, x0, y0, x0 + radius, y0);
+ vkvg_line_to(cr, x1 - radius, y0);
+ vkvg_curve_to(cr, x1, y0, x1, y0, x1, (y0 + y1) / 2);
+ vkvg_curve_to(cr, x1, y1, x1, y1, x1 - radius, y1);
+ vkvg_line_to(cr, x0 + radius, y1);
+ vkvg_curve_to(cr, x0, y1, x0, y1, x0, (y0 + y1) / 2);
+ } else {
+ vkvg_move_to(cr, x0, y0 + radius);
+ vkvg_curve_to(cr, x0, y0, x0, y0, x0 + radius, y0);
+ vkvg_line_to(cr, x1 - radius, y0);
+ vkvg_curve_to(cr, x1, y0, x1, y0, x1, y0 + radius);
+ vkvg_line_to(cr, x1, y1 - radius);
+ vkvg_curve_to(cr, x1, y1, x1, y1, x1 - radius, y1);
+ vkvg_line_to(cr, x0 + radius, y1);
+ vkvg_curve_to(cr, x0, y1, x0, y1, x0, y1 - radius);
+ }
+ }
+ vkvg_close_path(cr);
+
+ vkvg_set_source_rgb(cr, 0.5f, 0.5f, 1);
+ vkvg_fill_preserve(cr);
+ vkvg_set_source_rgba(cr, 0.5f, 0, 0, 0.5f);
+ vkvg_set_line_width(cr, 10.0f);
+ vkvg_stroke(cr);
}
-void cairo_test_fill_and_stroke2 (VkvgContext cr){
- vkvg_move_to (cr, 128.0f, 25.6f);
- vkvg_line_to (cr, 230.4f, 230.4f);
- vkvg_rel_line_to (cr, -102.4f, 0.0);
- vkvg_curve_to (cr, 51.2f, 230.4f, 51.2f, 128.0f, 128.0f, 128.0f);
- vkvg_close_path (cr);
-
- vkvg_move_to (cr, 64.0f, 25.6f);
- vkvg_rel_line_to (cr, 51.2f, 51.2f);
- vkvg_rel_line_to (cr, -51.2f, 51.2f);
- vkvg_rel_line_to (cr, -51.2f, -51.2f);
- vkvg_close_path (cr);
-
- /*vkvg_translate(cr,100,100);
- vkvg_move_to (cr, 100, 100);
- vkvg_line_to(cr,300,300);
- vkvg_line_to(cr,100,300);*/
-
-
- vkvg_set_line_width (cr, 10.0f);
- vkvg_set_source_rgb (cr, 0, 0, 1);
- vkvg_fill_preserve (cr);
- vkvg_set_source_rgb (cr, 0, 0, 0);
- vkvg_stroke (cr);
+void cairo_test_fill_and_stroke2(VkvgContext cr) {
+ vkvg_move_to(cr, 128.0f, 25.6f);
+ vkvg_line_to(cr, 230.4f, 230.4f);
+ vkvg_rel_line_to(cr, -102.4f, 0.0);
+ vkvg_curve_to(cr, 51.2f, 230.4f, 51.2f, 128.0f, 128.0f, 128.0f);
+ vkvg_close_path(cr);
+
+ vkvg_move_to(cr, 64.0f, 25.6f);
+ vkvg_rel_line_to(cr, 51.2f, 51.2f);
+ vkvg_rel_line_to(cr, -51.2f, 51.2f);
+ vkvg_rel_line_to(cr, -51.2f, -51.2f);
+ vkvg_close_path(cr);
+
+ /*vkvg_translate(cr,100,100);
+ vkvg_move_to (cr, 100, 100);
+ vkvg_line_to(cr,300,300);
+ vkvg_line_to(cr,100,300);*/
+
+ vkvg_set_line_width(cr, 10.0f);
+ vkvg_set_source_rgb(cr, 0, 0, 1);
+ vkvg_fill_preserve(cr);
+ vkvg_set_source_rgb(cr, 0, 0, 0);
+ vkvg_stroke(cr);
}
-void cairo_print_arc_neg (VkvgContext cr){
- float xc = 128.0f;
- float yc = 128.0f;
- float radius = 100.0f;
- float angle1 = 45.0f * (M_PIF/180.0f); /* angles are specified */
- float angle2 = 180.0f * (M_PIF/180.0f); /* in radians */
-
- vkvg_set_source_rgba(cr, 0, 0, 0, 1);
- vkvg_set_line_width (cr, 10.0f);
- vkvg_arc_negative (cr, xc, yc, radius, angle1, angle2);
- vkvg_stroke (cr);
-
- /* draw helping lines */
- vkvg_set_source_rgba (cr, 1, 0.2f, 0.2f, 0.6f);
- vkvg_set_line_width (cr, 6.0f);
-
- vkvg_arc (cr, xc, yc, 10.0f, 0, 2.f*M_PIF);
- vkvg_fill (cr);
-
- vkvg_arc (cr, xc, yc, radius, angle1, angle1);
- vkvg_line_to (cr, xc, yc);
- vkvg_arc (cr, xc, yc, radius, angle2, angle2);
- //vkvg_line_to (cr, xc, yc);
- vkvg_stroke (cr);
-
+void cairo_print_arc_neg(VkvgContext cr) {
+ float xc = 128.0f;
+ float yc = 128.0f;
+ float radius = 100.0f;
+ float angle1 = 45.0f * (M_PIF / 180.0f); /* angles are specified */
+ float angle2 = 180.0f * (M_PIF / 180.0f); /* in radians */
+
+ vkvg_set_source_rgba(cr, 0, 0, 0, 1);
+ vkvg_set_line_width(cr, 10.0f);
+ vkvg_arc_negative(cr, xc, yc, radius, angle1, angle2);
+ vkvg_stroke(cr);
+
+ /* draw helping lines */
+ vkvg_set_source_rgba(cr, 1, 0.2f, 0.2f, 0.6f);
+ vkvg_set_line_width(cr, 6.0f);
+
+ vkvg_arc(cr, xc, yc, 10.0f, 0, 2.f * M_PIF);
+ vkvg_fill(cr);
+
+ vkvg_arc(cr, xc, yc, radius, angle1, angle1);
+ vkvg_line_to(cr, xc, yc);
+ vkvg_arc(cr, xc, yc, radius, angle2, angle2);
+ // vkvg_line_to (cr, xc, yc);
+ vkvg_stroke(cr);
}
-void cairo_test_line_caps (VkvgContext cr) {
- vkvg_set_source_rgb (cr, 0, 0, 0);
- vkvg_set_line_width (cr, 30.0f);
- vkvg_set_line_cap (cr, VKVG_LINE_CAP_BUTT); /* default */
- vkvg_move_to (cr, 64.0f, 50.0f); vkvg_line_to (cr, 64.0f, 200.0f);
- vkvg_stroke (cr);
- vkvg_set_line_cap (cr, VKVG_LINE_CAP_ROUND);
- vkvg_move_to (cr, 128.0f, 50.0f); vkvg_line_to (cr, 128.0f, 200.0f);
- vkvg_stroke (cr);
- vkvg_set_line_cap (cr, VKVG_LINE_CAP_SQUARE);
- vkvg_move_to (cr, 192.0f, 50.0f); vkvg_line_to (cr, 192.0f, 200.0f);
- vkvg_stroke (cr);
-
- /* draw helping lines */
- vkvg_set_source_rgb (cr, 1, 0.2f, 0.2f);
- vkvg_set_line_width (cr, 2.56f);
- vkvg_move_to (cr, 64.0f, 50.0f); vkvg_line_to (cr, 64.0f, 200.0f);
- vkvg_move_to (cr, 128.0f, 50.0f); vkvg_line_to (cr, 128.0f, 200.0f);
- vkvg_move_to (cr, 192.0f, 50.0f); vkvg_line_to (cr, 192.0f, 200.0f);
- vkvg_stroke (cr);
+void cairo_test_line_caps(VkvgContext cr) {
+ vkvg_set_source_rgb(cr, 0, 0, 0);
+ vkvg_set_line_width(cr, 30.0f);
+ vkvg_set_line_cap(cr, VKVG_LINE_CAP_BUTT); /* default */
+ vkvg_move_to(cr, 64.0f, 50.0f);
+ vkvg_line_to(cr, 64.0f, 200.0f);
+ vkvg_stroke(cr);
+ vkvg_set_line_cap(cr, VKVG_LINE_CAP_ROUND);
+ vkvg_move_to(cr, 128.0f, 50.0f);
+ vkvg_line_to(cr, 128.0f, 200.0f);
+ vkvg_stroke(cr);
+ vkvg_set_line_cap(cr, VKVG_LINE_CAP_SQUARE);
+ vkvg_move_to(cr, 192.0f, 50.0f);
+ vkvg_line_to(cr, 192.0f, 200.0f);
+ vkvg_stroke(cr);
+
+ /* draw helping lines */
+ vkvg_set_source_rgb(cr, 1, 0.2f, 0.2f);
+ vkvg_set_line_width(cr, 2.56f);
+ vkvg_move_to(cr, 64.0f, 50.0f);
+ vkvg_line_to(cr, 64.0f, 200.0f);
+ vkvg_move_to(cr, 128.0f, 50.0f);
+ vkvg_line_to(cr, 128.0f, 200.0f);
+ vkvg_move_to(cr, 192.0f, 50.0f);
+ vkvg_line_to(cr, 192.0f, 200.0f);
+ vkvg_stroke(cr);
}
-void cairo_test_line_joins (VkvgContext cr) {
- vkvg_set_source_rgb (cr, 0, 0, 0);
- vkvg_set_line_width (cr, 40.96f);
- vkvg_move_to (cr, 76.8f, 84.48f);
- vkvg_rel_line_to (cr, 51.2f, -51.2f);
- vkvg_rel_line_to (cr, 51.2f, 51.2f);
- vkvg_set_line_join (cr, VKVG_LINE_JOIN_MITER); /* default */
- vkvg_stroke (cr);
-
- vkvg_move_to (cr, 76.8f, 161.28f);
- vkvg_rel_line_to (cr, 51.2f, -51.2f);
- vkvg_rel_line_to (cr, 51.2f, 51.2f);
- vkvg_set_line_join (cr, VKVG_LINE_JOIN_BEVEL);
- vkvg_stroke (cr);
-
- vkvg_move_to (cr, 76.8f, 238.08f);
- vkvg_rel_line_to (cr, 51.2f, -51.2f);
- vkvg_rel_line_to (cr, 51.2f, 51.2f);
- vkvg_set_line_join (cr, VKVG_LINE_JOIN_ROUND);
- vkvg_stroke (cr);
-
- /* draw helping lines */
- vkvg_set_source_rgb (cr, 1, 0.2f, 0.2f);
- vkvg_set_line_width (cr, 2.56f);
- vkvg_set_line_join (cr, VKVG_LINE_JOIN_MITER);
- vkvg_move_to (cr, 76.8f, 84.48f);
- vkvg_rel_line_to (cr, 51.2f, -51.2f);
- vkvg_rel_line_to (cr, 51.2f, 51.2f);
- vkvg_move_to (cr, 76.8f, 161.28f);
- vkvg_rel_line_to (cr, 51.2f, -51.2f);
- vkvg_rel_line_to (cr, 51.2f, 51.2f);
- vkvg_move_to (cr, 76.8f, 238.08f);
- vkvg_rel_line_to (cr, 51.2f, -51.2f);
- vkvg_rel_line_to (cr, 51.2f, 51.2f);
-
- vkvg_stroke (cr);
-
+void cairo_test_line_joins(VkvgContext cr) {
+ vkvg_set_source_rgb(cr, 0, 0, 0);
+ vkvg_set_line_width(cr, 40.96f);
+ vkvg_move_to(cr, 76.8f, 84.48f);
+ vkvg_rel_line_to(cr, 51.2f, -51.2f);
+ vkvg_rel_line_to(cr, 51.2f, 51.2f);
+ vkvg_set_line_join(cr, VKVG_LINE_JOIN_MITER); /* default */
+ vkvg_stroke(cr);
+
+ vkvg_move_to(cr, 76.8f, 161.28f);
+ vkvg_rel_line_to(cr, 51.2f, -51.2f);
+ vkvg_rel_line_to(cr, 51.2f, 51.2f);
+ vkvg_set_line_join(cr, VKVG_LINE_JOIN_BEVEL);
+ vkvg_stroke(cr);
+
+ vkvg_move_to(cr, 76.8f, 238.08f);
+ vkvg_rel_line_to(cr, 51.2f, -51.2f);
+ vkvg_rel_line_to(cr, 51.2f, 51.2f);
+ vkvg_set_line_join(cr, VKVG_LINE_JOIN_ROUND);
+ vkvg_stroke(cr);
+
+ /* draw helping lines */
+ vkvg_set_source_rgb(cr, 1, 0.2f, 0.2f);
+ vkvg_set_line_width(cr, 2.56f);
+ vkvg_set_line_join(cr, VKVG_LINE_JOIN_MITER);
+ vkvg_move_to(cr, 76.8f, 84.48f);
+ vkvg_rel_line_to(cr, 51.2f, -51.2f);
+ vkvg_rel_line_to(cr, 51.2f, 51.2f);
+ vkvg_move_to(cr, 76.8f, 161.28f);
+ vkvg_rel_line_to(cr, 51.2f, -51.2f);
+ vkvg_rel_line_to(cr, 51.2f, 51.2f);
+ vkvg_move_to(cr, 76.8f, 238.08f);
+ vkvg_rel_line_to(cr, 51.2f, -51.2f);
+ vkvg_rel_line_to(cr, 51.2f, 51.2f);
+
+ vkvg_stroke(cr);
}
-void cairo_print_arc (VkvgContext cr) {
- float xc = 128.0f;
- float yc = 128.0f;
- float radius = 100.0f;
- float angle1 = 45.0f * (M_PIF/180.0f); /* angles are specified */
- float angle2 = 180.0f * (M_PIF/180.0f); /* in radians */
-
- vkvg_set_source_rgba(cr, 0, 0, 0, 1);
- vkvg_set_line_width (cr, 10.0f);
- vkvg_arc (cr, xc, yc, radius, angle1, angle2);
- vkvg_stroke (cr);
-
- /* draw helping lines */
- vkvg_set_source_rgba(cr, 1, 0.2f, 0.2f, 0.6f);
- vkvg_set_line_width (cr, 6.0f);
-
- vkvg_arc (cr, xc, yc, 10.0f, 0, 2.f*M_PIF);
- vkvg_fill (cr);
-
- vkvg_arc (cr, xc, yc, radius, angle1, angle1);
- vkvg_line_to (cr, xc, yc);
- vkvg_arc (cr, xc, yc, radius, angle2, angle2);
- vkvg_stroke (cr);
+void cairo_print_arc(VkvgContext cr) {
+ float xc = 128.0f;
+ float yc = 128.0f;
+ float radius = 100.0f;
+ float angle1 = 45.0f * (M_PIF / 180.0f); /* angles are specified */
+ float angle2 = 180.0f * (M_PIF / 180.0f); /* in radians */
+
+ vkvg_set_source_rgba(cr, 0, 0, 0, 1);
+ vkvg_set_line_width(cr, 10.0f);
+ vkvg_arc(cr, xc, yc, radius, angle1, angle2);
+ vkvg_stroke(cr);
+
+ /* draw helping lines */
+ vkvg_set_source_rgba(cr, 1, 0.2f, 0.2f, 0.6f);
+ vkvg_set_line_width(cr, 6.0f);
+
+ vkvg_arc(cr, xc, yc, 10.0f, 0, 2.f * M_PIF);
+ vkvg_fill(cr);
+
+ vkvg_arc(cr, xc, yc, radius, angle1, angle1);
+ vkvg_line_to(cr, xc, yc);
+ vkvg_arc(cr, xc, yc, radius, angle2, angle2);
+ vkvg_stroke(cr);
}
static float rotation = 0.f;
-void cairo_tests () {
- rotation+=0.002f;
+void cairo_tests() {
+ rotation += 0.002f;
- vkvg_matrix_t mat;
- vkvg_matrix_init_translate (&mat, panX,panY);
- vkvg_matrix_scale(&mat,zoom,zoom);
- vkvg_matrix_translate (&mat, 400,400);
- vkvg_matrix_rotate(&mat,rotation);
- vkvg_matrix_translate(&mat,-400.f,-400.f);
+ vkvg_matrix_t mat;
+ vkvg_matrix_init_translate(&mat, panX, panY);
+ vkvg_matrix_scale(&mat, zoom, zoom);
+ vkvg_matrix_translate(&mat, 400, 400);
+ vkvg_matrix_rotate(&mat, rotation);
+ vkvg_matrix_translate(&mat, -400.f, -400.f);
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+ vkvg_set_source_rgba(ctx, 1.0f, 1.0f, 1.0f, 1);
+ vkvg_paint(ctx);
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_source_rgba(ctx,1.0f,1.0f,1.0f,1);
- vkvg_paint(ctx);
+ // vkvg_set_matrix(ctx,&mat);
+ vkvg_translate(ctx, panX, panY);
+ vkvg_scale(ctx, zoom, zoom);
+ vkvg_translate(ctx, 400, 400);
+ vkvg_rotate(ctx, rotation);
+ vkvg_translate(ctx, -400.f, -400.f);
- //vkvg_set_matrix(ctx,&mat);
- vkvg_translate (ctx, panX,panY);
- vkvg_scale(ctx,zoom,zoom);
- vkvg_translate (ctx, 400,400);
- vkvg_rotate(ctx,rotation);
- vkvg_translate(ctx,-400.f,-400.f);
+ cairo_print_arc(ctx);
- cairo_print_arc(ctx);
+ vkvg_translate(ctx, 200, 0);
+ cairo_test_fill_rule(ctx);
- vkvg_translate(ctx,200,0);
- cairo_test_fill_rule(ctx);
+ vkvg_translate(ctx, 250, 0);
+ cairo_test_rounded_rect(ctx);
- vkvg_translate(ctx,250,0);
- cairo_test_rounded_rect(ctx);
+ vkvg_translate(ctx, -450, 250);
+ cairo_test_fill_and_stroke2(ctx);
- vkvg_translate(ctx,-450,250);
- cairo_test_fill_and_stroke2(ctx);
+ vkvg_translate(ctx, 250, 0);
+ cairo_print_arc_neg(ctx);
- vkvg_translate(ctx,250,0);
- cairo_print_arc_neg(ctx);
+ vkvg_translate(ctx, 250, 0);
+ cairo_test_text(ctx);
- vkvg_translate(ctx,250,0);
- cairo_test_text(ctx);
+ vkvg_translate(ctx, -500, 250);
+ cairo_test_curves(ctx);
- vkvg_translate(ctx,-500,250);
- cairo_test_curves(ctx);
+ vkvg_translate(ctx, 250, 0);
+ cairo_test_line_joins(ctx);
- vkvg_translate(ctx,250,0);
- cairo_test_line_joins(ctx);
+ vkvg_translate(ctx, 250, 0);
+ cairo_test_line_caps(ctx);
- vkvg_translate(ctx,250,0);
- cairo_test_line_caps(ctx);
-
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
-
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (cairo_tests, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(cairo_tests, argc, argv);
+ return 0;
}
#include "test.h"
-static const char* txt = "The quick brown fox jumps over the lazy dog";
+static const char *txt = "The quick brown fox jumps over the lazy dog";
void print(VkvgContext ctx, float penY, uint32_t size) {
- vkvg_set_font_size(ctx,size);
- vkvg_move_to(ctx, 10, penY);
- vkvg_show_text (ctx,txt);
+ vkvg_set_font_size(ctx, size);
+ vkvg_move_to(ctx, 10, penY);
+ vkvg_show_text(ctx, txt);
}
-void print_boxed(VkvgContext ctx, const char* text, float penX, float penY, uint32_t size) {
- vkvg_set_font_size(ctx,size);
- vkvg_text_extents_t te = {0};
- vkvg_text_extents(ctx,text,&te);
- vkvg_font_extents_t fe = {0};
- vkvg_font_extents(ctx, &fe);
-
- vkvg_move_to(ctx, penX, penY);
- vkvg_rectangle(ctx, penX, penY -fe.ascent, te.width, fe.height);
- vkvg_set_source_rgb(ctx,0.2f,0.2f,0.7f);
- vkvg_fill(ctx);
-
- vkvg_move_to(ctx, penX, penY);
- vkvg_set_source_rgb(ctx,1,1,1);
- vkvg_show_text (ctx,text);
+void print_boxed(VkvgContext ctx, const char *text, float penX, float penY, uint32_t size) {
+ vkvg_set_font_size(ctx, size);
+ vkvg_text_extents_t te = {0};
+ vkvg_text_extents(ctx, text, &te);
+ vkvg_font_extents_t fe = {0};
+ vkvg_font_extents(ctx, &fe);
+
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_rectangle(ctx, penX, penY - fe.ascent, te.width, fe.height);
+ vkvg_set_source_rgb(ctx, 0.2f, 0.2f, 0.7f);
+ vkvg_fill(ctx);
+
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
+ vkvg_show_text(ctx, text);
}
-void print_unboxed(VkvgContext ctx, const char* text, float penX, float penY, uint32_t size) {
- vkvg_set_font_size(ctx,size);
- vkvg_move_to(ctx, penX, penY);
- vkvg_set_source_rgb(ctx,1,1,1);
- vkvg_show_text (ctx,text);
+void print_unboxed(VkvgContext ctx, const char *text, float penX, float penY, uint32_t size) {
+ vkvg_set_font_size(ctx, size);
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
+ vkvg_show_text(ctx, text);
}
void test2() {
- VkvgContext ctx = vkvg_create(surf);
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_color_t bg = {0.0,0.0,0.0,1};
- vkvg_color_t fg = {1.0f,1.0f,1.0f,1};
+ vkvg_color_t bg = {0.0, 0.0, 0.0, 1};
+ vkvg_color_t fg = {1.0f, 1.0f, 1.0f, 1};
- vkvg_set_source_rgba(ctx,bg.r,bg.g,bg.b,bg.a);
- vkvg_paint(ctx);
- vkvg_set_source_rgba(ctx,fg.r,fg.g,fg.b,fg.a);
- //vkvg_select_font_face(ctx, "droid");
- vkvg_select_font_face(ctx, "times");
+ vkvg_set_source_rgba(ctx, bg.r, bg.g, bg.b, bg.a);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgba(ctx, fg.r, fg.g, fg.b, fg.a);
+ // vkvg_select_font_face(ctx, "droid");
+ vkvg_select_font_face(ctx, "times");
+ float penY = 10.f;
- float penY = 10.f;
+ for (uint32_t size = 4; size < 39; size++) {
+ print(ctx, (float)penY, size);
+ penY += size;
+ }
- for (uint32_t size = 4; size < 39; size++) {
- print(ctx,(float)penY,size);
- penY+=size;
- }
-
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
void test1() {
- VkvgContext ctx = vkvg_create(surf);
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_color_t fg = {0.0,0.0,0.0,1};
- vkvg_color_t bg = {0.9f,0.9f,0.9f,1};
+ vkvg_color_t fg = {0.0, 0.0, 0.0, 1};
+ vkvg_color_t bg = {0.9f, 0.9f, 0.9f, 1};
- vkvg_set_source_rgba(ctx,bg.r,bg.g,bg.b,bg.a);
- vkvg_paint(ctx);
- vkvg_set_source_rgba(ctx,fg.r,fg.g,fg.b,fg.a);
+ vkvg_set_source_rgba(ctx, bg.r, bg.g, bg.b, bg.a);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgba(ctx, fg.r, fg.g, fg.b, fg.a);
- uint32_t size = 8;
- float penY = 100.f;
+ uint32_t size = 8;
+ float penY = 100.f;
- vkvg_set_font_size(ctx,size);
+ vkvg_set_font_size(ctx, size);
- vkvg_select_font_face(ctx, "mono");
- vkvg_move_to(ctx, 100.f,penY);
- vkvg_show_text (ctx,txt);
+ vkvg_select_font_face(ctx, "mono");
+ vkvg_move_to(ctx, 100.f, penY);
+ vkvg_show_text(ctx, txt);
- penY += 1.2f * size;
+ penY += 1.2f * size;
- vkvg_select_font_face(ctx, "times");
- vkvg_move_to(ctx, 100.f, penY);
- vkvg_show_text (ctx,txt);
+ vkvg_select_font_face(ctx, "times");
+ vkvg_move_to(ctx, 100.f, penY);
+ vkvg_show_text(ctx, txt);
- penY += 1.2f * size;
+ penY += 1.2f * size;
- vkvg_select_font_face(ctx, "arial:italic");
- vkvg_move_to(ctx, 100.f, penY);
- vkvg_show_text (ctx,txt);
+ vkvg_select_font_face(ctx, "arial:italic");
+ vkvg_move_to(ctx, 100.f, penY);
+ vkvg_show_text(ctx, txt);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
-void test(){
- VkvgContext ctx = vkvg_create(surf);
-
- //vkvg_color_t fg = {0.2,0.2,0.2,1};
- vkvg_color_t fg = {0.0,0.0,0.0,1};
- vkvg_color_t bg = {1.0f,1.0f,1.0f,1};
- vkvg_set_source_rgba(ctx,bg.r,bg.g,bg.b,bg.a);
- vkvg_paint(ctx);
-
- float size = 19;
- float penY = 50;
- float penX = 10;
-
- /*vkvg_rectangle(ctx,30,0,100,400);
- vkvg_clip(ctx);*/
-
- //vkvg_select_font_face(ctx, "/usr/local/share/fonts/DroidSansMono.ttf");
- //vkvg_select_font_face(ctx, "/usr/share/fonts/truetype/unifont/unifont.ttf");
-
- vkvg_set_font_size (ctx, 12);
- vkvg_select_font_face (ctx, "droid");
- vkvg_font_extents_t fe;
- vkvg_font_extents (ctx, &fe);
- vkvg_move_to (ctx, penX,penY);
- vkvg_set_source_rgba (ctx, fg.r, fg.g, fg.b, fg.a);
- vkvg_text_extents_t te;
- vkvg_text_extents (ctx, "abcdefghijk", &te);
- vkvg_show_text (ctx, "abcdefghijk");
- penX += te.x_advance;
- vkvg_move_to(ctx, penX,penY);
- vkvg_show_text (ctx,"*abcdefghijk2");
- penY += 2.f*size;
-
- vkvg_select_font_face(ctx, "times");
- vkvg_move_to(ctx, penX,penY);
- vkvg_show_text (ctx,"abcdefghijklmnopqrstuvwxyz");
- penY+=size;
-
- vkvg_select_font_face(ctx, "droid");
- vkvg_move_to(ctx, penX,penY);
- vkvg_show_text (ctx,"lmnopqrstuvwxyz123456789");
- penY+=size;
-
- vkvg_select_font_face(ctx, "times:bold");
- vkvg_move_to(ctx, penX,penY);
- vkvg_show_text (ctx,"abcdefghijklmnopqrstuvwxyz");
- penY+=size;
-
- vkvg_select_font_face(ctx, "droid");
- vkvg_move_to(ctx, penX,penY);
- vkvg_show_text (ctx,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- penY+=size;
-
- vkvg_select_font_face(ctx, "arial:italic");
- vkvg_move_to(ctx, penX,penY);
- vkvg_show_text (ctx,"abcdefghijklmnopqrstuvwxyz");
- penY+=size;
-
- vkvg_select_font_face(ctx, "arial");
- vkvg_move_to(ctx, penX,penY);
- vkvg_show_text (ctx,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- penY+=size;
- vkvg_move_to(ctx, penX,penY);
- vkvg_show_text (ctx,"this is a test");
- penY+=size;
- vkvg_move_to(ctx, penX,penY);
- vkvg_show_text (ctx,"this is another test to see if label is working");
- penY+=size;
-
- vkvg_select_font_face(ctx, "mono");
- vkvg_move_to(ctx, penX,penY);
- vkvg_show_text (ctx,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- penY+=size;
-
- vkvg_move_to(ctx, 80,400);
- vkvg_show_text (ctx,"Ленивый рыжий кот");
-
- vkvg_move_to(ctx, 150,250);
- vkvg_show_text (ctx,"test string é€");
- vkvg_move_to(ctx, 150,300);
- vkvg_show_text (ctx,"كسول الزنجبيل القط");
- vkvg_move_to(ctx, 150,350);
- vkvg_show_text (ctx,"懶惰的姜貓");
-
- //vkvg_show_text (ctx,"ABCDABCD");
- //vkvg_show_text (ctx,"j");
-
- vkvg_destroy(ctx);
+void test() {
+ VkvgContext ctx = vkvg_create(surf);
+
+ // vkvg_color_t fg = {0.2,0.2,0.2,1};
+ vkvg_color_t fg = {0.0, 0.0, 0.0, 1};
+ vkvg_color_t bg = {1.0f, 1.0f, 1.0f, 1};
+ vkvg_set_source_rgba(ctx, bg.r, bg.g, bg.b, bg.a);
+ vkvg_paint(ctx);
+
+ float size = 19;
+ float penY = 50;
+ float penX = 10;
+
+ /*vkvg_rectangle(ctx,30,0,100,400);
+ vkvg_clip(ctx);*/
+
+ // vkvg_select_font_face(ctx, "/usr/local/share/fonts/DroidSansMono.ttf");
+ // vkvg_select_font_face(ctx, "/usr/share/fonts/truetype/unifont/unifont.ttf");
+
+ vkvg_set_font_size(ctx, 12);
+ vkvg_select_font_face(ctx, "droid");
+ vkvg_font_extents_t fe;
+ vkvg_font_extents(ctx, &fe);
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_set_source_rgba(ctx, fg.r, fg.g, fg.b, fg.a);
+ vkvg_text_extents_t te;
+ vkvg_text_extents(ctx, "abcdefghijk", &te);
+ vkvg_show_text(ctx, "abcdefghijk");
+ penX += te.x_advance;
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_show_text(ctx, "*abcdefghijk2");
+ penY += 2.f * size;
+
+ vkvg_select_font_face(ctx, "times");
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_show_text(ctx, "abcdefghijklmnopqrstuvwxyz");
+ penY += size;
+
+ vkvg_select_font_face(ctx, "droid");
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_show_text(ctx, "lmnopqrstuvwxyz123456789");
+ penY += size;
+
+ vkvg_select_font_face(ctx, "times:bold");
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_show_text(ctx, "abcdefghijklmnopqrstuvwxyz");
+ penY += size;
+
+ vkvg_select_font_face(ctx, "droid");
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_show_text(ctx, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ penY += size;
+
+ vkvg_select_font_face(ctx, "arial:italic");
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_show_text(ctx, "abcdefghijklmnopqrstuvwxyz");
+ penY += size;
+
+ vkvg_select_font_face(ctx, "arial");
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_show_text(ctx, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ penY += size;
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_show_text(ctx, "this is a test");
+ penY += size;
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_show_text(ctx, "this is another test to see if label is working");
+ penY += size;
+
+ vkvg_select_font_face(ctx, "mono");
+ vkvg_move_to(ctx, penX, penY);
+ vkvg_show_text(ctx, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ penY += size;
+
+ vkvg_move_to(ctx, 80, 400);
+ vkvg_show_text(ctx, "Ленивый рыжий кот");
+
+ vkvg_move_to(ctx, 150, 250);
+ vkvg_show_text(ctx, "test string é€");
+ vkvg_move_to(ctx, 150, 300);
+ vkvg_show_text(ctx, "كسول الزنجبيل القط");
+ vkvg_move_to(ctx, 150, 350);
+ vkvg_show_text(ctx, "懶惰的姜貓");
+
+ // vkvg_show_text (ctx,"ABCDABCD");
+ // vkvg_show_text (ctx,"j");
+
+ vkvg_destroy(ctx);
}
-void single_font_and_size () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
- for (uint32_t i=0; i<test_size; i++) {
- randomize_color(ctx);
- float x = rndf() * test_width;
- float y = rndf() * test_height;
- vkvg_select_font_face(ctx,"mono");
- vkvg_set_font_size(ctx, 20);
- vkvg_move_to(ctx,x,y);
- vkvg_show_text(ctx,"This is a test string!");
- }
- vkvg_destroy(ctx);
+void single_font_and_size() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+ for (uint32_t i = 0; i < test_size; i++) {
+ randomize_color(ctx);
+ float x = rndf() * test_width;
+ float y = rndf() * test_height;
+ vkvg_select_font_face(ctx, "mono");
+ vkvg_set_font_size(ctx, 20);
+ vkvg_move_to(ctx, x, y);
+ vkvg_show_text(ctx, "This is a test string!");
+ }
+ vkvg_destroy(ctx);
}
-void simple_text () {
- VkvgContext ctx = vkvg_create(surf);
-
- vkvg_set_source_rgb (ctx, 0, 0, 0);
- vkvg_paint (ctx);
- vkvg_set_source_rgb (ctx, 1, 1, 1);
+void simple_text() {
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_load_font_from_path (ctx, "data/DancingScript-Regular.ttf", "dancing");
- print_boxed (ctx, "abcdefghijklmnopqrstuvwxyz", 20,60,20);
- print_boxed (ctx, "ABC", 20,160,60);
- vkvg_select_font_face (ctx, "mono");
- print_boxed (ctx, "This is a test string!", 20, 250, 20);
- print_boxed (ctx, "ANOTHER ONE TO CHECK..", 20, 350, 20);
+ vkvg_set_source_rgb(ctx, 0, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
- vkvg_destroy (ctx);
+ vkvg_load_font_from_path(ctx, "data/DancingScript-Regular.ttf", "dancing");
+ print_boxed(ctx, "abcdefghijklmnopqrstuvwxyz", 20, 60, 20);
+ print_boxed(ctx, "ABC", 20, 160, 60);
+ vkvg_select_font_face(ctx, "mono");
+ print_boxed(ctx, "This is a test string!", 20, 250, 20);
+ print_boxed(ctx, "ANOTHER ONE TO CHECK..", 20, 350, 20);
+ vkvg_destroy(ctx);
}
-void font_file_path () {
- VkvgContext ctx = vkvg_create(surf);
-
- vkvg_set_source_rgb (ctx, 0, 0, 0);
- vkvg_paint (ctx);
- vkvg_set_source_rgb (ctx, 1, 1, 1);
- vkvg_load_font_from_path (ctx, "data/DancingScript-Regular.ttf", "droid");
- print_boxed (ctx, "This is a test string!", 50,20,12);
- print_boxed (ctx, "This is a test string!", 50,50,20);
- print_boxed (ctx, "ANOTHER ONE TO CHECK..", 50,80,20);
- print_boxed (ctx, "this is another string to check if ligature are well set", 10,120,20);
- vkvg_destroy (ctx);
+void font_file_path() {
+ VkvgContext ctx = vkvg_create(surf);
+
+ vkvg_set_source_rgb(ctx, 0, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
+ vkvg_load_font_from_path(ctx, "data/DancingScript-Regular.ttf", "droid");
+ print_boxed(ctx, "This is a test string!", 50, 20, 12);
+ print_boxed(ctx, "This is a test string!", 50, 50, 20);
+ print_boxed(ctx, "ANOTHER ONE TO CHECK..", 50, 80, 20);
+ print_boxed(ctx, "this is another string to check if ligature are well set", 10, 120, 20);
+ vkvg_destroy(ctx);
}
-void random_size () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
- vkvg_select_font_face(ctx,"mono");
- for (uint32_t i=0; i<test_size; i++) {
- randomize_color(ctx);
- float x = rndf() * test_width;
- float y = rndf() * test_height;
- uint32_t c = (uint32_t)(rndf() * 120)+1;
-
- vkvg_set_font_size(ctx, c);
- vkvg_move_to(ctx,x,y);
- vkvg_show_text(ctx,"This is a test string!");
- }
- vkvg_destroy(ctx);
+void random_size() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+ vkvg_select_font_face(ctx, "mono");
+ for (uint32_t i = 0; i < test_size; i++) {
+ randomize_color(ctx);
+ float x = rndf() * test_width;
+ float y = rndf() * test_height;
+ uint32_t c = (uint32_t)(rndf() * 120) + 1;
+
+ vkvg_set_font_size(ctx, c);
+ vkvg_move_to(ctx, x, y);
+ vkvg_show_text(ctx, "This is a test string!");
+ }
+ vkvg_destroy(ctx);
}
-const char* const fonts[] =
- { "mono", "droid", "times", "arial", "times:bold"};
-
-void random_font_and_size () {
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
-
- for (uint32_t i=0; i<test_size; i++) {
- randomize_color(ctx);
- float x = rndf() * test_width;
- float y = rndf() * test_height;
- uint32_t c = (uint32_t)(rndf() * 80)+1;
- uint32_t f = (uint32_t)(rndf() * 4);
-
- vkvg_set_font_size(ctx, c);
- vkvg_select_font_face(ctx, fonts[f]);
- vkvg_move_to(ctx,x,y);
- vkvg_show_text(ctx,"This is a test string!");
- }
- vkvg_destroy(ctx);
+const char *const fonts[] = {"mono", "droid", "times", "arial", "times:bold"};
+
+void random_font_and_size() {
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+
+ for (uint32_t i = 0; i < test_size; i++) {
+ randomize_color(ctx);
+ float x = rndf() * test_width;
+ float y = rndf() * test_height;
+ uint32_t c = (uint32_t)(rndf() * 80) + 1;
+ uint32_t f = (uint32_t)(rndf() * 4);
+
+ vkvg_set_font_size(ctx, c);
+ vkvg_select_font_face(ctx, fonts[f]);
+ vkvg_move_to(ctx, x, y);
+ vkvg_show_text(ctx, "This is a test string!");
+ }
+ vkvg_destroy(ctx);
}
-void proto_sinaitic () {
- VkvgContext ctx = vkvg_create(surf);
+void proto_sinaitic() {
+ VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgb (ctx, 0, 0, 0);
- vkvg_paint (ctx);
- vkvg_set_source_rgb (ctx, 1, 1, 1);
+ vkvg_set_source_rgb(ctx, 0, 0, 0);
+ vkvg_paint(ctx);
+ vkvg_set_source_rgb(ctx, 1, 1, 1);
- vkvg_load_font_from_path (ctx, "data/Proto-Sinaitic15.ttf", "sinaitic");
- print_boxed (ctx, "hwhy", 100, 150, 60);
+ vkvg_load_font_from_path(ctx, "data/Proto-Sinaitic15.ttf", "sinaitic");
+ print_boxed(ctx, "hwhy", 100, 150, 60);
- vkvg_destroy (ctx);
+ vkvg_destroy(ctx);
}
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (simple_text, argc, argv);
- PERFORM_TEST (font_file_path, argc, argv);
- PERFORM_TEST (single_font_and_size, argc, argv);
- PERFORM_TEST (random_size, argc, argv);
- PERFORM_TEST (random_font_and_size, argc, argv);
- PERFORM_TEST (test, argc, argv);
- PERFORM_TEST (test1, argc, argv);
- PERFORM_TEST (test2, argc, argv);
- PERFORM_TEST (proto_sinaitic, argc, argv);
-
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(simple_text, argc, argv);
+ PERFORM_TEST(font_file_path, argc, argv);
+ PERFORM_TEST(single_font_and_size, argc, argv);
+ PERFORM_TEST(random_size, argc, argv);
+ PERFORM_TEST(random_font_and_size, argc, argv);
+ PERFORM_TEST(test, argc, argv);
+ PERFORM_TEST(test1, argc, argv);
+ PERFORM_TEST(test2, argc, argv);
+ PERFORM_TEST(proto_sinaitic, argc, argv);
+
+ return 0;
}
#include "vectors.h"
#include "vkvg_context_internal.h"
-vkvg_fill_rule_t fillrule = VKVG_FILL_RULE_NON_ZERO;
-static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
-float lineWidth = 3.0f;
-vkvg_line_join_t lineJoin = VKVG_LINE_JOIN_MITER;
-vkvg_line_cap_t lineCap = VKVG_LINE_CAP_BUTT;
-bool isClosed = false;
-bool startWithArc = false, endWithArc = false;
-float angle = 0;
-float r;
-vec2 mouse;
-
-void draw (){
- angle += 0.001f;
-
- VkvgContext ctx = vkvg_create(surf);
- vkvg_clear(ctx);
-
- float r = fabsf(test_width/2 - mouse.x)/zoom;
-
- vkvg_new_path(ctx);
- vkvg_set_source_rgba(ctx,1,0,0,1);
- vkvg_set_line_width (ctx,lineWidth/zoom);
-
- vkvg_translate(ctx, test_width/2, test_height/2);
- vkvg_scale(ctx, zoom, zoom);
- //vkvg_rotate (ctx, angle);
-
- vkvg_matrix_t mat;
- vkvg_get_matrix(ctx, &mat);
- float sx, sy;
- vkvg_matrix_get_scale(&mat, &sx, &sy);
-
- vkvg_arc (ctx,0,0,r, 0, M_PIF*2);
- vkvg_fill(ctx);
-
- float steps = _get_arc_step(ctx, r);
- vkvg_identity_matrix(ctx);
-
- vkvg_set_source_rgba(ctx,1,1,1,1);
- char txt[100];
- sprintf(txt, "scale: %f, %f", sx, sy);
- vkvg_move_to(ctx,10,10);
- vkvg_show_text(ctx,txt);
- sprintf(txt, "angle: %f", angle);
- vkvg_move_to(ctx,10,25);
- vkvg_show_text(ctx,txt);
- sprintf(txt, "radius: %f", r);
- vkvg_move_to(ctx,10,40);
- vkvg_show_text(ctx,txt);
- sprintf(txt, "zoom: %f", zoom);
- vkvg_move_to(ctx,10,55);
- vkvg_show_text(ctx,txt);
- sprintf(txt, "arc step: %f", steps);
- vkvg_move_to(ctx,10,70);
- vkvg_show_text(ctx,txt);
- sprintf(txt, "steps: %d", (int)roundf(2.0f*M_PI / steps));
- vkvg_move_to(ctx,10,85);
- vkvg_show_text(ctx,txt);
-
- vkvg_destroy(ctx);
+vkvg_fill_rule_t fillrule = VKVG_FILL_RULE_NON_ZERO;
+static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
+float lineWidth = 3.0f;
+vkvg_line_join_t lineJoin = VKVG_LINE_JOIN_MITER;
+vkvg_line_cap_t lineCap = VKVG_LINE_CAP_BUTT;
+bool isClosed = false;
+bool startWithArc = false, endWithArc = false;
+float angle = 0;
+float r;
+vec2 mouse;
+
+void draw() {
+ angle += 0.001f;
+
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_clear(ctx);
+
+ float r = fabsf(test_width / 2 - mouse.x) / zoom;
+
+ vkvg_new_path(ctx);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
+ vkvg_set_line_width(ctx, lineWidth / zoom);
+
+ vkvg_translate(ctx, test_width / 2, test_height / 2);
+ vkvg_scale(ctx, zoom, zoom);
+ // vkvg_rotate (ctx, angle);
+
+ vkvg_matrix_t mat;
+ vkvg_get_matrix(ctx, &mat);
+ float sx, sy;
+ vkvg_matrix_get_scale(&mat, &sx, &sy);
+
+ vkvg_arc(ctx, 0, 0, r, 0, M_PIF * 2);
+ vkvg_fill(ctx);
+
+ float steps = _get_arc_step(ctx, r);
+ vkvg_identity_matrix(ctx);
+
+ vkvg_set_source_rgba(ctx, 1, 1, 1, 1);
+ char txt[100];
+ sprintf(txt, "scale: %f, %f", sx, sy);
+ vkvg_move_to(ctx, 10, 10);
+ vkvg_show_text(ctx, txt);
+ sprintf(txt, "angle: %f", angle);
+ vkvg_move_to(ctx, 10, 25);
+ vkvg_show_text(ctx, txt);
+ sprintf(txt, "radius: %f", r);
+ vkvg_move_to(ctx, 10, 40);
+ vkvg_show_text(ctx, txt);
+ sprintf(txt, "zoom: %f", zoom);
+ vkvg_move_to(ctx, 10, 55);
+ vkvg_show_text(ctx, txt);
+ sprintf(txt, "arc step: %f", steps);
+ vkvg_move_to(ctx, 10, 70);
+ vkvg_show_text(ctx, txt);
+ sprintf(txt, "steps: %d", (int)roundf(2.0f * M_PI / steps));
+ vkvg_move_to(ctx, 10, 85);
+ vkvg_show_text(ctx, txt);
+
+ vkvg_destroy(ctx);
}
-static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
- if (action != GLFW_PRESS)
- return;
- switch (key) {
- case GLFW_KEY_ESCAPE :
- glfwSetWindowShouldClose(window, GLFW_TRUE);
- break;
- case GLFW_KEY_KP_ADD :
- zoom *= 2.0f;
- break;
- case GLFW_KEY_KP_SUBTRACT :
- zoom *= 0.5f;
- break;
+static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+ if (action != GLFW_PRESS)
+ return;
+ switch (key) {
+ case GLFW_KEY_ESCAPE:
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+ break;
+ case GLFW_KEY_KP_ADD:
+ zoom *= 2.0f;
+ break;
+ case GLFW_KEY_KP_SUBTRACT:
+ zoom *= 0.5f;
+ break;
#ifdef VKVG_WIRED_DEBUG
- case GLFW_KEY_F1:
- vkvg_wired_debug ^= (1U << 0);
- break;
- case GLFW_KEY_F2:
- vkvg_wired_debug ^= (1U << 1);
- break;
- case GLFW_KEY_F3:
- vkvg_wired_debug ^= (1U << 2);
- break;
+ case GLFW_KEY_F1:
+ vkvg_wired_debug ^= (1U << 0);
+ break;
+ case GLFW_KEY_F2:
+ vkvg_wired_debug ^= (1U << 1);
+ break;
+ case GLFW_KEY_F3:
+ vkvg_wired_debug ^= (1U << 2);
+ break;
#endif
- }
+ }
}
-static void mouse_move_callback(GLFWwindow* window, double x, double y){
- if (mouseDown) {
- mouse = (vec2) {x, y};
- }
+static void mouse_move_callback(GLFWwindow *window, double x, double y) {
+ if (mouseDown) {
+ mouse = (vec2){x, y};
+ }
}
-static void scroll_callback(GLFWwindow* window, double x, double y){
- if (y<0.f)
- zoom *= 0.5f;
- else
- zoom *= 2.0f;
+static void scroll_callback(GLFWwindow *window, double x, double y) {
+ if (y < 0.f)
+ zoom *= 0.5f;
+ else
+ zoom *= 2.0f;
}
-static void mouse_button_callback(GLFWwindow* window, int but, int state, int modif){
- if (but != GLFW_MOUSE_BUTTON_1)
- return;
- if (state == GLFW_TRUE)
- mouseDown = true;
- else
- mouseDown = false;
+static void mouse_button_callback(GLFWwindow *window, int but, int state, int modif) {
+ if (but != GLFW_MOUSE_BUTTON_1)
+ return;
+ if (state == GLFW_TRUE)
+ mouseDown = true;
+ else
+ mouseDown = false;
}
+int main(int argc, char *argv[]) {
+ _parse_args(argc, argv);
+ VkEngine e;
+ e = vkengine_create(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
-int main(int argc, char* argv[]) {
+ VkhPresenter r = e->renderer;
+ vkengine_set_key_callback(e, key_callback);
+ vkengine_set_mouse_but_callback(e, mouse_button_callback);
+ vkengine_set_cursor_pos_callback(e, mouse_move_callback);
+ vkengine_set_scroll_callback(e, scroll_callback);
- _parse_args (argc, argv);
- VkEngine e;
- e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
+ bool deferredResolve = false;
- VkhPresenter r = e->renderer;
- vkengine_set_key_callback (e, key_callback);
- vkengine_set_mouse_but_callback(e, mouse_button_callback);
- vkengine_set_cursor_pos_callback(e, mouse_move_callback);
- vkengine_set_scroll_callback(e, scroll_callback);
+ device = vkvg_device_create_from_vk_multisample(vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0,
+ samples, deferredResolve);
+ surf = vkvg_surface_create(device, test_width, test_height);
- bool deferredResolve = false;
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
- device = vkvg_device_create_from_vk_multisample(vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0, samples, deferredResolve);
- surf = vkvg_surface_create(device, test_width, test_height);
+ mouse = (vec2){test_width * 0.75, test_height * 0.5f};
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ while (!vkengine_should_close(e)) {
+ glfwPollEvents();
- mouse = (vec2){test_width*0.75,test_height*0.5f};
+ draw();
- while (!vkengine_should_close (e)) {
- glfwPollEvents();
+ if (!vkh_presenter_draw(r)) {
+ vkh_presenter_get_size(r, &test_width, &test_height);
+ vkvg_surface_destroy(surf);
+ surf = vkvg_surface_create(device, test_width, test_height);
+ vkh_presenter_build_blit_cmd(r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+ vkDeviceWaitIdle(r->dev->dev);
+ continue;
+ }
+ }
+ vkDeviceWaitIdle(e->dev->dev);
- draw ();
+ vkvg_surface_destroy(surf);
- if (!vkh_presenter_draw (r)){
- vkh_presenter_get_size (r, &test_width, &test_height);
- vkvg_surface_destroy (surf);
- surf = vkvg_surface_create(device, test_width, test_height);
- vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
- vkDeviceWaitIdle(r->dev->dev);
- continue;
- }
- }
- vkDeviceWaitIdle(e->dev->dev);
+ vkvg_device_destroy(device);
- vkvg_surface_destroy (surf);
+ vkengine_destroy(e);
- vkvg_device_destroy (device);
-
- vkengine_destroy (e);
-
- return 0;
+ return 0;
}
#include "test.h"
-
-void _test_rounded_rect (VkvgContext cr) {
- /* a custom shape that could be wrapped in a function */
- float x0 = -100, /* parameters like vkvg_rectangle */
- y0 = -100,
- rect_width = 200,
- rect_height = 200,
- radius = 102.4f; /* and an approximate curvature radius */
-
- float x1,y1;
-
- x1=x0+rect_width;
- y1=y0+rect_height;
- if (!rect_width || !rect_height)
- return;
- if (rect_width/2<radius) {
- if (rect_height/2<radius) {
- vkvg_move_to (cr, x0, (y0 + y1)/2);
- vkvg_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
- vkvg_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
- vkvg_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
- vkvg_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
- } else {
- vkvg_move_to (cr, x0, y0 + radius);
- vkvg_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
- vkvg_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
- vkvg_line_to (cr, x1 , y1 - radius);
- vkvg_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
- vkvg_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
- }
- } else {
- if (rect_height/2<radius) {
- vkvg_move_to (cr, x0, (y0 + y1)/2);
- vkvg_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
- vkvg_line_to (cr, x1 - radius, y0);
- vkvg_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
- vkvg_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
- vkvg_line_to (cr, x0 + radius, y1);
- vkvg_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
- } else {
- vkvg_move_to (cr, x0, y0 + radius);
- vkvg_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
- vkvg_line_to (cr, x1 - radius, y0);
- vkvg_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
- vkvg_line_to (cr, x1 , y1 - radius);
- vkvg_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
- vkvg_line_to (cr, x0 + radius, y1);
- vkvg_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
- }
- }
- vkvg_close_path (cr);
-
- vkvg_set_source_rgb (cr, 0.5f, 0.5f, 1);
- vkvg_fill_preserve (cr);
- vkvg_set_source_rgba (cr, 0.5f, 0, 0, 0.5f);
- vkvg_set_line_width (cr, 10.0f);
- vkvg_stroke (cr);
+void _test_rounded_rect(VkvgContext cr) {
+ /* a custom shape that could be wrapped in a function */
+ float x0 = -100, /* parameters like vkvg_rectangle */
+ y0 = -100, rect_width = 200, rect_height = 200, radius = 102.4f; /* and an approximate curvature radius */
+
+ float x1, y1;
+
+ x1 = x0 + rect_width;
+ y1 = y0 + rect_height;
+ if (!rect_width || !rect_height)
+ return;
+ if (rect_width / 2 < radius) {
+ if (rect_height / 2 < radius) {
+ vkvg_move_to(cr, x0, (y0 + y1) / 2);
+ vkvg_curve_to(cr, x0, y0, x0, y0, (x0 + x1) / 2, y0);
+ vkvg_curve_to(cr, x1, y0, x1, y0, x1, (y0 + y1) / 2);
+ vkvg_curve_to(cr, x1, y1, x1, y1, (x1 + x0) / 2, y1);
+ vkvg_curve_to(cr, x0, y1, x0, y1, x0, (y0 + y1) / 2);
+ } else {
+ vkvg_move_to(cr, x0, y0 + radius);
+ vkvg_curve_to(cr, x0, y0, x0, y0, (x0 + x1) / 2, y0);
+ vkvg_curve_to(cr, x1, y0, x1, y0, x1, y0 + radius);
+ vkvg_line_to(cr, x1, y1 - radius);
+ vkvg_curve_to(cr, x1, y1, x1, y1, (x1 + x0) / 2, y1);
+ vkvg_curve_to(cr, x0, y1, x0, y1, x0, y1 - radius);
+ }
+ } else {
+ if (rect_height / 2 < radius) {
+ vkvg_move_to(cr, x0, (y0 + y1) / 2);
+ vkvg_curve_to(cr, x0, y0, x0, y0, x0 + radius, y0);
+ vkvg_line_to(cr, x1 - radius, y0);
+ vkvg_curve_to(cr, x1, y0, x1, y0, x1, (y0 + y1) / 2);
+ vkvg_curve_to(cr, x1, y1, x1, y1, x1 - radius, y1);
+ vkvg_line_to(cr, x0 + radius, y1);
+ vkvg_curve_to(cr, x0, y1, x0, y1, x0, (y0 + y1) / 2);
+ } else {
+ vkvg_move_to(cr, x0, y0 + radius);
+ vkvg_curve_to(cr, x0, y0, x0, y0, x0 + radius, y0);
+ vkvg_line_to(cr, x1 - radius, y0);
+ vkvg_curve_to(cr, x1, y0, x1, y0, x1, y0 + radius);
+ vkvg_line_to(cr, x1, y1 - radius);
+ vkvg_curve_to(cr, x1, y1, x1, y1, x1 - radius, y1);
+ vkvg_line_to(cr, x0 + radius, y1);
+ vkvg_curve_to(cr, x0, y1, x0, y1, x0, y1 - radius);
+ }
+ }
+ vkvg_close_path(cr);
+
+ vkvg_set_source_rgb(cr, 0.5f, 0.5f, 1);
+ vkvg_fill_preserve(cr);
+ vkvg_set_source_rgba(cr, 0.5f, 0, 0, 0.5f);
+ vkvg_set_line_width(cr, 10.0f);
+ vkvg_stroke(cr);
}
-
static float rotation = 0.f;
-void cairo_tests () {
- rotation+=0.002f;
+void cairo_tests() {
+ rotation += 0.002f;
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_source_rgba(ctx,1.0f,1.0f,1.0f,1);
- vkvg_paint(ctx);
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+ vkvg_set_source_rgba(ctx, 1.0f, 1.0f, 1.0f, 1);
+ vkvg_paint(ctx);
- vkvg_set_line_width(ctx,10);
+ vkvg_set_line_width(ctx, 10);
- vkvg_set_source_rgb(ctx,0,0,1);
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
- vkvg_translate (ctx, test_width/2,test_height/2);
- vkvg_rotate(ctx, rotation);
- //vkvg_scale(ctx, 200,200);
+ vkvg_translate(ctx, test_width / 2, test_height / 2);
+ vkvg_rotate(ctx, rotation);
+ // vkvg_scale(ctx, 200,200);
- vkvg_arc (ctx, 0, 0, 150, 0, M_PI*1.5);
- vkvg_stroke(ctx);
+ vkvg_arc(ctx, 0, 0, 150, 0, M_PI * 1.5);
+ vkvg_stroke(ctx);
- _test_rounded_rect(ctx);
+ _test_rounded_rect(ctx);
- vkvg_destroy(ctx);
+ vkvg_destroy(ctx);
}
-
int main(int argc, char *argv[]) {
- no_test_size = true;
- PERFORM_TEST (cairo_tests, argc, argv);
- return 0;
+ no_test_size = true;
+ PERFORM_TEST(cairo_tests, argc, argv);
+ return 0;
}
#include <stdarg.h>
#include <ctype.h>
-static VkvgDevice dev;
+static VkvgDevice dev;
static VkvgSurface svgSurf = NULL;
-static double scale = 1;
-
-
-static char* filename = NULL;
-static char* directory = NULL;
-static DIR * pCurrentDir = NULL;
-struct dirent *dir = NULL;
-static int iconSize = -1;
-static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
-static uint32_t width=512, height=512, margin = 10;
-static double scrollX, scrollY;
-static bool paused = false, repaintIconList = true;
-
+static double scale = 1;
+
+static char *filename = NULL;
+static char *directory = NULL;
+static DIR *pCurrentDir = NULL;
+struct dirent *dir = NULL;
+static int iconSize = -1;
+static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
+static uint32_t width = 512, height = 512, margin = 10;
+static double scrollX, scrollY;
+static bool paused = false, repaintIconList = true;
struct stat file_stat;
-#define NORMAL_COLOR "\x1B[0m"
-#define GREEN "\x1B[32m"
-#define BLUE "\x1B[34m"
+#define NORMAL_COLOR "\x1B[0m"
+#define GREEN "\x1B[32m"
+#define BLUE "\x1B[34m"
-static int svg_file_count;
+static int svg_file_count;
static float maxScroll;
/* not defined in c11, ok to define here only for sample */
#ifndef DT_DIR
- # define DT_DIR 4
+#define DT_DIR 4
#endif
-int _count_svg_files () {
- struct dirent *de;
- rewinddir (pCurrentDir);
- int i = 0;
- while ((de = readdir(pCurrentDir)) != NULL) {
- if(de->d_type != DT_DIR && !strcasecmp(strrchr(de->d_name, '\0') - 4, ".svg"))
- i++;
- }
- return i;
+int _count_svg_files() {
+ struct dirent *de;
+ rewinddir(pCurrentDir);
+ int i = 0;
+ while ((de = readdir(pCurrentDir)) != NULL) {
+ if (de->d_type != DT_DIR && !strcasecmp(strrchr(de->d_name, '\0') - 4, ".svg"))
+ i++;
+ }
+ return i;
}
-void readSVG (VkEngine e) {
- struct stat sb;
- VkvgSurface newSvgSurf = NULL;
- if (iconSize > 0 && pCurrentDir) {
- if (!repaintIconList)
- return;
- char tmp[FILENAME_MAX];
- double x = 0, y = 0;
- int cellSize = iconSize + margin;
- int iconPerLine = ceil((double)(width-iconSize) / cellSize);
- int lineToSkip = floor(scrollY / cellSize);
- int iconToSkip = lineToSkip * iconPerLine;
-
- y = (lineToSkip * cellSize) - scrollY;
-
- newSvgSurf = vkvg_surface_create(dev, width, height);
- VkvgContext ctx = vkvg_create(newSvgSurf);
-
- struct dirent *de;
- rewinddir (pCurrentDir);
- int i = 0;
- while ((de = readdir(pCurrentDir)) != NULL) {
- if(de->d_type != DT_DIR) {
- if (!strcasecmp(strrchr(de->d_name, '\0') - 4, ".svg")) {
- if (i >= iconToSkip) {
- sprintf(tmp, "%s%s", directory, de->d_name);
- VkvgSurface surf = vkvg_surface_create_from_svg (dev, iconSize, iconSize, tmp);
-
- if (surf) {
- vkvg_set_source_surface(ctx, surf, x, y);
- vkvg_paint(ctx);
- vkvg_surface_destroy(surf);
- }
- x += iconSize + margin;
- if (x > width - iconSize) {
- x = 0;
- y += iconSize + margin;
- if (y >= height)
- break;
- }
- }
- i++;
- }
- }
- }
- vkvg_destroy(ctx);
- repaintIconList = false;
- }else if (filename) {
- vkengine_set_title(e, filename);
- if (stat(filename, &sb) == -1) {
- printf ("Unable to stat file: %s\n", filename);
- exit(EXIT_FAILURE);
- }
- if (sb.st_mtime == file_stat.st_mtime)
- return;
- file_stat = sb;
- newSvgSurf = vkvg_surface_create_from_svg(dev, width, height, filename);
- } else if (dir) {
- char tmp[FILENAME_MAX];
- sprintf(tmp, "%s/%s", directory, dir->d_name);
- vkengine_set_title(e, tmp);
- if (stat(tmp, &sb) == -1) {
- printf ("Unable to stat file: %s\n", tmp);
- exit(EXIT_FAILURE);
- }
- if (sb.st_mtime == file_stat.st_mtime)
- return;
- file_stat = sb;
- newSvgSurf = vkvg_surface_create_from_svg(dev, width, height, tmp);
- }
-
- //vkengine_wait_idle(e);
-
- if (svgSurf)
- vkvg_surface_destroy(svgSurf);
- svgSurf = newSvgSurf;
-
- //vkengine_wait_idle(e);
+void readSVG(VkEngine e) {
+ struct stat sb;
+ VkvgSurface newSvgSurf = NULL;
+ if (iconSize > 0 && pCurrentDir) {
+ if (!repaintIconList)
+ return;
+ char tmp[FILENAME_MAX];
+ double x = 0, y = 0;
+ int cellSize = iconSize + margin;
+ int iconPerLine = ceil((double)(width - iconSize) / cellSize);
+ int lineToSkip = floor(scrollY / cellSize);
+ int iconToSkip = lineToSkip * iconPerLine;
+
+ y = (lineToSkip * cellSize) - scrollY;
+
+ newSvgSurf = vkvg_surface_create(dev, width, height);
+ VkvgContext ctx = vkvg_create(newSvgSurf);
+
+ struct dirent *de;
+ rewinddir(pCurrentDir);
+ int i = 0;
+ while ((de = readdir(pCurrentDir)) != NULL) {
+ if (de->d_type != DT_DIR) {
+ if (!strcasecmp(strrchr(de->d_name, '\0') - 4, ".svg")) {
+ if (i >= iconToSkip) {
+ sprintf(tmp, "%s%s", directory, de->d_name);
+ VkvgSurface surf = vkvg_surface_create_from_svg(dev, iconSize, iconSize, tmp);
+
+ if (surf) {
+ vkvg_set_source_surface(ctx, surf, x, y);
+ vkvg_paint(ctx);
+ vkvg_surface_destroy(surf);
+ }
+ x += iconSize + margin;
+ if (x > width - iconSize) {
+ x = 0;
+ y += iconSize + margin;
+ if (y >= height)
+ break;
+ }
+ }
+ i++;
+ }
+ }
+ }
+ vkvg_destroy(ctx);
+ repaintIconList = false;
+ } else if (filename) {
+ vkengine_set_title(e, filename);
+ if (stat(filename, &sb) == -1) {
+ printf("Unable to stat file: %s\n", filename);
+ exit(EXIT_FAILURE);
+ }
+ if (sb.st_mtime == file_stat.st_mtime)
+ return;
+ file_stat = sb;
+ newSvgSurf = vkvg_surface_create_from_svg(dev, width, height, filename);
+ } else if (dir) {
+ char tmp[FILENAME_MAX];
+ sprintf(tmp, "%s/%s", directory, dir->d_name);
+ vkengine_set_title(e, tmp);
+ if (stat(tmp, &sb) == -1) {
+ printf("Unable to stat file: %s\n", tmp);
+ exit(EXIT_FAILURE);
+ }
+ if (sb.st_mtime == file_stat.st_mtime)
+ return;
+ file_stat = sb;
+ newSvgSurf = vkvg_surface_create_from_svg(dev, width, height, tmp);
+ }
+
+ // vkengine_wait_idle(e);
+
+ if (svgSurf)
+ vkvg_surface_destroy(svgSurf);
+ svgSurf = newSvgSurf;
+
+ // vkengine_wait_idle(e);
#ifdef VKVG_DBG_STATS
- vkvg_debug_stats_t dbgStats = vkvg_device_get_stats (dev);
- vkvg_device_reset_stats (dev);
- printf("maximum point array size = %d\n", dbgStats.sizePoints);
- printf("maximum path array size = %d\n", dbgStats.sizePathes);
- printf("maximum size of host vertice cache = %d\n", dbgStats.sizeVertices);
- printf("maximum size of host index cache = %d\n", dbgStats.sizeIndices);
- printf("maximum size of vulkan vertex buffer = %d\n", dbgStats.sizeVBO);
- printf("maximum size of vulkan index buffer = %d\n", dbgStats.sizeIBO);
+ vkvg_debug_stats_t dbgStats = vkvg_device_get_stats(dev);
+ vkvg_device_reset_stats(dev);
+ printf("maximum point array size = %d\n", dbgStats.sizePoints);
+ printf("maximum path array size = %d\n", dbgStats.sizePathes);
+ printf("maximum size of host vertice cache = %d\n", dbgStats.sizeVertices);
+ printf("maximum size of host index cache = %d\n", dbgStats.sizeIndices);
+ printf("maximum size of vulkan vertex buffer = %d\n", dbgStats.sizeVBO);
+ printf("maximum size of vulkan index buffer = %d\n", dbgStats.sizeIBO);
#endif
-
}
-struct dirent *get_next_svg_file_in_current_directory (bool cycle) {
- struct dirent *de;
- while ((de = readdir(pCurrentDir)) != NULL) {
- if(de->d_type != DT_DIR) {
- if (!strcasecmp(strrchr(de->d_name, '\0') - 4, ".svg"))
- return de;
- }
- }
- if (!cycle)
- return NULL;
- rewinddir (pCurrentDir);
- return get_next_svg_file_in_current_directory (false);
+struct dirent *get_next_svg_file_in_current_directory(bool cycle) {
+ struct dirent *de;
+ while ((de = readdir(pCurrentDir)) != NULL) {
+ if (de->d_type != DT_DIR) {
+ if (!strcasecmp(strrchr(de->d_name, '\0') - 4, ".svg"))
+ return de;
+ }
+ }
+ if (!cycle)
+ return NULL;
+ rewinddir(pCurrentDir);
+ return get_next_svg_file_in_current_directory(false);
}
-
-static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
- if (action == GLFW_RELEASE)
- return;
- switch (key) {
- case GLFW_KEY_SPACE:
- paused = !paused;
- break;
- case GLFW_KEY_R:
- //recording = !recording;
- file_stat = (struct stat){0};
- break;
- case GLFW_KEY_ESCAPE :
- glfwSetWindowShouldClose(window, GLFW_TRUE);
- break;
- case GLFW_KEY_ENTER :
- if (!pCurrentDir)
- break;
- dir = get_next_svg_file_in_current_directory(true);
- file_stat = (struct stat){0};
- break;
- case GLFW_KEY_KP_ADD:
- scale*=2.0;
- file_stat = (struct stat){0};
- break;
- case GLFW_KEY_KP_SUBTRACT:
- scale/=2.0;
- file_stat = (struct stat){0};
- break;
- }
+static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+ if (action == GLFW_RELEASE)
+ return;
+ switch (key) {
+ case GLFW_KEY_SPACE:
+ paused = !paused;
+ break;
+ case GLFW_KEY_R:
+ // recording = !recording;
+ file_stat = (struct stat){0};
+ break;
+ case GLFW_KEY_ESCAPE:
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+ break;
+ case GLFW_KEY_ENTER:
+ if (!pCurrentDir)
+ break;
+ dir = get_next_svg_file_in_current_directory(true);
+ file_stat = (struct stat){0};
+ break;
+ case GLFW_KEY_KP_ADD:
+ scale *= 2.0;
+ file_stat = (struct stat){0};
+ break;
+ case GLFW_KEY_KP_SUBTRACT:
+ scale /= 2.0;
+ file_stat = (struct stat){0};
+ break;
+ }
}
-static void scroll_callback(GLFWwindow* window, double x, double y) {
- if (iconSize == 0)
- return;
- scrollX -= x * 25;
- scrollY -= y * 25;
- if (scrollX < 0)
- scrollX = 0;
- if (scrollY < 0)
- scrollY = 0;
- else if (scrollY > maxScroll)
- scrollY = maxScroll;
- repaintIconList = true;
+static void scroll_callback(GLFWwindow *window, double x, double y) {
+ if (iconSize == 0)
+ return;
+ scrollX -= x * 25;
+ scrollY -= y * 25;
+ if (scrollX < 0)
+ scrollX = 0;
+ if (scrollY < 0)
+ scrollY = 0;
+ else if (scrollY > maxScroll)
+ scrollY = maxScroll;
+ repaintIconList = true;
}
-void print_help_and_exit () {
- printf("\nUsage: svgviewer [options] [svgfilepath]\n\n");
- printf("\t-o file.png:\toutput result to file then exit.\n");
- printf("\t-d directory:\tdirectory containing svg files, cycle pressing Enter.\n");
- printf("\t\t\tif the -d option is not specified, svgfile path is mandatory.\n");
- printf("\t-i size:\tif -d option is present, display all svg files as a list with the size specified.\n");
- printf("\t-m margin:\tset margin for the -i option\n");
- printf("\t-w width:\tset output surface width.\n");
- printf("\t-h height:\tset output surface height.\n");
- printf("\t-s samples:\tset sample count, set to 1 to disable multisampling.\n");
- printf("\n");
- exit(-1);
+void print_help_and_exit() {
+ printf("\nUsage: svgviewer [options] [svgfilepath]\n\n");
+ printf("\t-o file.png:\toutput result to file then exit.\n");
+ printf("\t-d directory:\tdirectory containing svg files, cycle pressing Enter.\n");
+ printf("\t\t\tif the -d option is not specified, svgfile path is mandatory.\n");
+ printf("\t-i size:\tif -d option is present, display all svg files as a list with the size specified.\n");
+ printf("\t-m margin:\tset margin for the -i option\n");
+ printf("\t-w width:\tset output surface width.\n");
+ printf("\t-h height:\tset output surface height.\n");
+ printf("\t-s samples:\tset sample count, set to 1 to disable multisampling.\n");
+ printf("\n");
+ exit(-1);
}
-
-int main (int argc, char *argv[]){
- int i = 1;
- char* output = NULL;
-
- while (i < argc) {
- int argLen = strlen(argv[i]);
- if (argv[i][0] == '-') {
-
- if (argLen < 2) print_help_and_exit ();
-
- switch (argv[i][1]) {
- case 'd':
- if (argc < ++i + 1) print_help_and_exit();
- directory = argv[i];
- break;
- case 'w':
- if (argc < ++i + 1) print_help_and_exit();
- width = atoi(argv[i]);
- break;
- case 'h':
- if (argc < ++i + 1) print_help_and_exit();
- height = atoi(argv[i]);
- break;
- case 's':
- if (argc < ++i + 1) print_help_and_exit();
- samples = (VkSampleCountFlags)atoi(argv[i]);
- break;
- case 'i':
- if (argc < ++i + 1) print_help_and_exit();
- iconSize = atoi(argv[i]);
- break;
- case 'm':
- if (argc < ++i + 1) print_help_and_exit();
- margin = atoi(argv[i]);
- break;
- case 'o':
- if (argc < ++i + 1) print_help_and_exit();
- output = argv[i];
- break;
- default:
- print_help_and_exit();
- }
- } else
- filename = argv[i];
- i++;
- }
- if (!filename && !directory)
- print_help_and_exit();
-
- VkEngine e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,VK_PRESENT_MODE_FIFO_KHR, width, height);
- vkengine_set_key_callback (e, key_callback);
- vkengine_set_scroll_callback(e, scroll_callback);
- vkvg_device_create_info_t info = {
- samples,
- false,
- vkh_app_get_inst(e->app),
- vkengine_get_physical_device(e),
- vkengine_get_device(e),
- vkengine_get_queue_fam_idx(e),
- 0
- };
- dev = vkvg_device_create(&info);
-
- VkvgSurface surf = NULL;
-
- if (output) {
- surf = vkvg_surface_create_from_svg(dev, width, height, filename);
- vkvg_surface_write_to_png (surf, output);
- } else {
-
- surf = vkvg_surface_create(dev, width, height);
-
- vkh_presenter_build_blit_cmd (e->renderer, vkvg_surface_get_vk_image(surf), width, height);
-
- if (directory) {
- pCurrentDir = opendir(directory);
- if(!pCurrentDir) {
- printf ("Directory not found: %s\n", directory);
- exit(EXIT_FAILURE);
- }
- dir = get_next_svg_file_in_current_directory(false);
- if (!dir) {
- printf ("No .svg file found in %s\n", directory);
- closedir(pCurrentDir);
- exit(EXIT_FAILURE);
- }
- if (iconSize > 0) {
- svg_file_count = _count_svg_files();
- int cellSize = iconSize + margin;
- int iconPerLine = ceil((double)(width-iconSize) / cellSize);
- int visibleLines = ceil((double)(height) / cellSize);
- int totLines = ceil((double)svg_file_count / iconPerLine);
- maxScroll = (totLines-visibleLines) * cellSize;
- }
- }
-
-
-
- while (!vkengine_should_close (e)) {
- //vkvg_log_level = VKVG_LOG_INFO_CMD;
- readSVG (e);
- //vkvg_log_level = VKVG_LOG_ERR;
-
- VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgb(ctx,0.1,0.1,0.1);
- vkvg_paint(ctx);
-
- if (svgSurf) {
- vkvg_set_source_surface(ctx, svgSurf, 0, 0);
- vkvg_paint(ctx);
- } else {
- vkvg_set_line_width(ctx,10);
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_move_to(ctx, 0,0);
- vkvg_line_to(ctx, 512,512);
- vkvg_move_to(ctx, 0,512);
- vkvg_line_to(ctx, 512,0);
- vkvg_stroke(ctx);
-
- }
- vkvg_destroy(ctx);
-
- glfwPollEvents();
-
- if (!vkh_presenter_draw (e->renderer)){
- vkh_presenter_get_size (e->renderer, &width, &height);
- vkvg_surface_destroy (surf);
- surf = vkvg_surface_create(dev, width, height);
- vkh_presenter_build_blit_cmd (e->renderer, vkvg_surface_get_vk_image(surf), width, height);
- vkengine_wait_idle(e);
- repaintIconList = true;
- continue;
- }
-
- }
-
- vkengine_wait_idle(e);
-
- }
-
- if (svgSurf)
- vkvg_surface_destroy(svgSurf);
- vkvg_surface_destroy(surf);
- vkvg_device_destroy(dev);
- vkengine_destroy(e);
-
- if (pCurrentDir)
- closedir(pCurrentDir);
+int main(int argc, char *argv[]) {
+ int i = 1;
+ char *output = NULL;
+
+ while (i < argc) {
+ int argLen = strlen(argv[i]);
+ if (argv[i][0] == '-') {
+
+ if (argLen < 2)
+ print_help_and_exit();
+
+ switch (argv[i][1]) {
+ case 'd':
+ if (argc < ++i + 1)
+ print_help_and_exit();
+ directory = argv[i];
+ break;
+ case 'w':
+ if (argc < ++i + 1)
+ print_help_and_exit();
+ width = atoi(argv[i]);
+ break;
+ case 'h':
+ if (argc < ++i + 1)
+ print_help_and_exit();
+ height = atoi(argv[i]);
+ break;
+ case 's':
+ if (argc < ++i + 1)
+ print_help_and_exit();
+ samples = (VkSampleCountFlags)atoi(argv[i]);
+ break;
+ case 'i':
+ if (argc < ++i + 1)
+ print_help_and_exit();
+ iconSize = atoi(argv[i]);
+ break;
+ case 'm':
+ if (argc < ++i + 1)
+ print_help_and_exit();
+ margin = atoi(argv[i]);
+ break;
+ case 'o':
+ if (argc < ++i + 1)
+ print_help_and_exit();
+ output = argv[i];
+ break;
+ default:
+ print_help_and_exit();
+ }
+ } else
+ filename = argv[i];
+ i++;
+ }
+ if (!filename && !directory)
+ print_help_and_exit();
+
+ VkEngine e = vkengine_create(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, width, height);
+ vkengine_set_key_callback(e, key_callback);
+ vkengine_set_scroll_callback(e, scroll_callback);
+ vkvg_device_create_info_t info = {samples,
+ false,
+ vkh_app_get_inst(e->app),
+ vkengine_get_physical_device(e),
+ vkengine_get_device(e),
+ vkengine_get_queue_fam_idx(e),
+ 0};
+ dev = vkvg_device_create(&info);
+
+ VkvgSurface surf = NULL;
+
+ if (output) {
+ surf = vkvg_surface_create_from_svg(dev, width, height, filename);
+ vkvg_surface_write_to_png(surf, output);
+ } else {
+
+ surf = vkvg_surface_create(dev, width, height);
+
+ vkh_presenter_build_blit_cmd(e->renderer, vkvg_surface_get_vk_image(surf), width, height);
+
+ if (directory) {
+ pCurrentDir = opendir(directory);
+ if (!pCurrentDir) {
+ printf("Directory not found: %s\n", directory);
+ exit(EXIT_FAILURE);
+ }
+ dir = get_next_svg_file_in_current_directory(false);
+ if (!dir) {
+ printf("No .svg file found in %s\n", directory);
+ closedir(pCurrentDir);
+ exit(EXIT_FAILURE);
+ }
+ if (iconSize > 0) {
+ svg_file_count = _count_svg_files();
+ int cellSize = iconSize + margin;
+ int iconPerLine = ceil((double)(width - iconSize) / cellSize);
+ int visibleLines = ceil((double)(height) / cellSize);
+ int totLines = ceil((double)svg_file_count / iconPerLine);
+ maxScroll = (totLines - visibleLines) * cellSize;
+ }
+ }
+
+ while (!vkengine_should_close(e)) {
+ // vkvg_log_level = VKVG_LOG_INFO_CMD;
+ readSVG(e);
+ // vkvg_log_level = VKVG_LOG_ERR;
+
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_source_rgb(ctx, 0.1, 0.1, 0.1);
+ vkvg_paint(ctx);
+
+ if (svgSurf) {
+ vkvg_set_source_surface(ctx, svgSurf, 0, 0);
+ vkvg_paint(ctx);
+ } else {
+ vkvg_set_line_width(ctx, 10);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_move_to(ctx, 0, 0);
+ vkvg_line_to(ctx, 512, 512);
+ vkvg_move_to(ctx, 0, 512);
+ vkvg_line_to(ctx, 512, 0);
+ vkvg_stroke(ctx);
+ }
+ vkvg_destroy(ctx);
+
+ glfwPollEvents();
+
+ if (!vkh_presenter_draw(e->renderer)) {
+ vkh_presenter_get_size(e->renderer, &width, &height);
+ vkvg_surface_destroy(surf);
+ surf = vkvg_surface_create(dev, width, height);
+ vkh_presenter_build_blit_cmd(e->renderer, vkvg_surface_get_vk_image(surf), width, height);
+ vkengine_wait_idle(e);
+ repaintIconList = true;
+ continue;
+ }
+ }
+
+ vkengine_wait_idle(e);
+ }
+
+ if (svgSurf)
+ vkvg_surface_destroy(svgSurf);
+ vkvg_surface_destroy(surf);
+ vkvg_device_destroy(dev);
+ vkengine_destroy(e);
+
+ if (pCurrentDir)
+ closedir(pCurrentDir);
}