AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
-AllowShortCaseLabelsOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: true
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: false
- name: configure
- run: cmake -B build_win64 -G "Visual Studio 17 2022" -A x64 -DVKVG_RECORDING=false -DVKVG_SVG=false -DGIT_SUBMODULE=true -DBUILD_SHARED_LIBS=OFF
+ run: cmake -B build_win64 -G "Visual Studio 17 2022" -A x64 -DVKVG_RECORDING=false -DVKVG_SVG=false -DBUILD_SHARED_LIBS=OFF
- name: build win64
run: cmake --build build_win64 --parallel
shell: bash
env:
VULKAN_SDK: ${{ github.workspace }}/VulkanSDK/x86_64
+ VULKAN_LAYER_PATH: ${{ github.workspace }}/VulkanSDK/x86_64/share/vulkan/explicit_layer.d"
steps:
- uses: actions/checkout@v4
ref: linux
persist-credentials: false
- run: echo "${{ env.VULKAN_SDK }}/bin" >> $GITHUB_PATH
- - run: sudo apt update && sudo apt install xorg-dev
+ - run: sudo apt update && sudo apt install xorg-dev libglfw3-dev xxd
- uses: actions/checkout@v4
with:
path: 'source'
persist-credentials: false
submodules: 'true'
- run: mkdir -p source/build
- - run: cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_config }} -G "Unix Makefiles" .. -DVKVG_RECORDING=false -DVKVG_SVG=false -DGIT_SUBMODULE=true
+ - run: cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_config }} -G "Unix Makefiles" .. -DVKVG_RECORDING=false -DVKVG_SVG=false
working-directory: source/build
- run: cmake --build . --config ${{ matrix.build_config }}
working-directory: source/build
-
mac_jorb:
runs-on: macos-latest
strategy:
path: 'source'
persist-credentials: false
- run: mkdir -p source/build
- - run: cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_config }} .. -DVKVG_RECORDING=false -DVKVG_SVG=false -DGIT_SUBMODULE=true
+ - run: cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_config }} .. -DVKVG_RECORDING=false -DVKVG_SVG=false
working-directory: source/build
- run: cmake --build . --config ${{ matrix.build_config }}
working-directory: source/build
--- /dev/null
+#!/bin/bash
+
+find . -iname "*.h" -o -iname "*.c" -o -iname "*.cpp" -o -iname "*.hpp" -not -path "build/*" \
+ | xargs clang-format -i -fallback-style=none
+
+exit 0
class BasicDrawTest : public DrawTestBase {
protected:
-
- void SetUp() override {
- surf = vkvg_surface_create(dev, 256, 256);
- }
+ void SetUp() override { surf = vkvg_surface_create(dev, 256, 256); }
};
TEST_F(BasicDrawTest, CtxSolidPaintRGB) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgb(ctx,1,0,0);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
TEST_F(BasicDrawTest, CtxSolidPaintRGBA) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgba(ctx,1,0,0,1);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
TEST_F(BasicDrawTest, CtxSolidPaintWithActiveTransform) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_translate(ctx,100,100);
+ vkvg_translate(ctx, 100, 100);
vkvg_rotate(ctx, 2.f);
- vkvg_set_source_rgba(ctx,1,0,0,1);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
TEST_F(BasicDrawTest, CtxSolidPaintOver) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgba(ctx,1,0,0,0.5);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.5);
vkvg_paint(ctx);
- vkvg_set_source_rgba(ctx,0,0,1,0.5);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 0.5);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
TEST_F(BasicDrawTest, CtxSolidPaintRectangle) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgb(ctx,1,0,0);
- vkvg_rectangle(ctx,50,50,200,150);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_rectangle(ctx, 50, 50, 200, 150);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
TEST_F(BasicDrawTest, CtxSolidPaintRectanglesOver) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgba(ctx,1,0,0,0.5f);
- vkvg_rectangle(ctx,50,50,100,100);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.5f);
+ vkvg_rectangle(ctx, 50, 50, 100, 100);
vkvg_paint(ctx);
- vkvg_set_source_rgba(ctx,0,0,1,0.5f);
- vkvg_rectangle(ctx,100,100,100,100);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 0.5f);
+ vkvg_rectangle(ctx, 100, 100, 100, 100);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
TEST_F(BasicDrawTest, CtxSolidFillOver) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgba(ctx,1,0,0,0.5);
- vkvg_rectangle(ctx,50,50,100,100);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.5);
+ vkvg_rectangle(ctx, 50, 50, 100, 100);
vkvg_fill(ctx);
- vkvg_set_source_rgba(ctx,0,0,1,0.5);
- vkvg_rectangle(ctx,100,100,100,100);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 0.5);
+ vkvg_rectangle(ctx, 100, 100, 100, 100);
vkvg_fill(ctx);
vkvg_destroy(ctx);
}
TEST_F(BasicDrawTest, CtxSolidPaintRectangleOver) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgba(ctx,1,0,0,0.5f);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.5f);
vkvg_paint(ctx);
- vkvg_set_source_rgba(ctx,0,0,1,0.5f);
- vkvg_rectangle(ctx,100,100,100,100);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 0.5f);
+ vkvg_rectangle(ctx, 100, 100, 100, 100);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
TEST_F(BasicDrawTest, CtxSolidPaintRectangleOverClipped) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_rectangle(ctx,90,90,70,70);
+ vkvg_rectangle(ctx, 90, 90, 70, 70);
vkvg_clip(ctx);
- vkvg_set_source_rgba(ctx,1,0,0,0.5);
- vkvg_rectangle(ctx,50,50,100,100);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.5);
+ vkvg_rectangle(ctx, 50, 50, 100, 100);
vkvg_fill(ctx);
- vkvg_set_source_rgba(ctx,0,0,1,0.5);
- vkvg_rectangle(ctx,100,100,100,100);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 0.5);
+ vkvg_rectangle(ctx, 100, 100, 100, 100);
vkvg_fill(ctx);
vkvg_destroy(ctx);
}
TEST_F(BasicDrawTest, CtxSolidPaintClipped) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_rectangle(ctx,50,50,200,150);
+ vkvg_rectangle(ctx, 50, 50, 200, 150);
vkvg_clip(ctx);
- vkvg_set_source_rgba(ctx,1,0,0,0.5f);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.5f);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
TEST_F(BasicDrawTest, CtxSolidPaintClippedOver) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgba(ctx,1,0,0,0.5f);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 0.5f);
vkvg_paint(ctx);
- vkvg_rectangle(ctx,50,50,200,150);
+ vkvg_rectangle(ctx, 50, 50, 200, 150);
vkvg_clip(ctx);
- vkvg_set_source_rgba(ctx,0,0,1,0.5f);
+ vkvg_set_source_rgba(ctx, 0, 0, 1, 0.5f);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
TEST_F(BasicDrawTest, CtxStrokeJoins) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgba(ctx,0,0,0,1);
+ vkvg_set_source_rgba(ctx, 0, 0, 0, 1);
vkvg_set_line_width(ctx, 20);
vkvg_set_line_join(ctx, VKVG_LINE_JOIN_BEVEL);
vkvg_set_line_join(ctx, VKVG_LINE_JOIN_MITER);
drawLineJoin(ctx);
- vkvg_translate(ctx, 0, 80 );
+ vkvg_translate(ctx, 0, 80);
vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND);
drawLineJoin(ctx);
compareWithRefImage();
}
void drawLineCap(VkvgContext ctx) {
- vkvg_set_source_rgba(ctx,0,0,0,1);
+ vkvg_set_source_rgba(ctx, 0, 0, 0, 1);
vkvg_set_line_width(ctx, 20);
vkvg_move_to(ctx, 50, 50);
vkvg_line_to(ctx, 200, 50);
vkvg_stroke(ctx);
vkvg_set_line_cap(ctx, VKVG_LINE_CAP_BUTT);
- vkvg_set_source_rgba(ctx,1,0,0,1);
+ vkvg_set_source_rgba(ctx, 1, 0, 0, 1);
vkvg_set_line_width(ctx, 2);
vkvg_move_to(ctx, 50, 50);
vkvg_line_to(ctx, 200, 50);
vkvg_stroke(ctx);
-
}
TEST_F(BasicDrawTest, CtxStrokeCaps) {
VkvgContext ctx = vkvg_create(surf);
vkvg_set_line_cap(ctx, VKVG_LINE_CAP_ROUND);
drawLineCap(ctx);
- vkvg_translate(ctx, 0, 50 );
+ vkvg_translate(ctx, 0, 50);
vkvg_set_line_cap(ctx, VKVG_LINE_CAP_SQUARE);
drawLineCap(ctx);
vkvg_destroy(ctx);
EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_surface_status(surf));
- //EXPECT_EQ(0, vkvg_get_reference_count(ctx));
+ // EXPECT_EQ(0, vkvg_get_reference_count(ctx));
EXPECT_EQ(1, vkvg_surface_get_reference_count(surf));
EXPECT_EQ(2, vkvg_device_get_reference_count(dev));
}
TEST_F(ContextTest, CtxDrawBasicNullContext) {
- //test method with context in error
+ // test method with context in error
VkvgContext ctx = vkvg_create(NULL);
EXPECT_NO_FATAL_FAILURE(vkvg_new_path(ctx));
EXPECT_NO_FATAL_FAILURE(vkvg_close_path(ctx));
EXPECT_NO_FATAL_FAILURE(vkvg_path_extents(ctx, NULL, NULL, NULL, NULL));
EXPECT_NO_FATAL_FAILURE(vkvg_get_current_point(ctx, NULL, NULL));
- EXPECT_NO_FATAL_FAILURE(vkvg_line_to(ctx,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_rel_line_to(ctx,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_move_to(ctx,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_rel_move_to(ctx,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_arc(ctx,0,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_arc_negative(ctx,0,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_curve_to(ctx,0,0,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_rel_curve_to(ctx,0,0,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_quadratic_to(ctx,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_rel_quadratic_to(ctx,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_rectangle(ctx,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_rounded_rectangle(ctx,0,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_rounded_rectangle2(ctx,0,0,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_ellipse(ctx,0,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_elliptic_arc_to(ctx,0,0,0,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_rel_elliptic_arc_to(ctx,0,0,0,0,0,0,0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_line_to(ctx, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_rel_line_to(ctx, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_move_to(ctx, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_rel_move_to(ctx, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_arc(ctx, 0, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_arc_negative(ctx, 0, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_curve_to(ctx, 0, 0, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_rel_curve_to(ctx, 0, 0, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_quadratic_to(ctx, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_rel_quadratic_to(ctx, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_rectangle(ctx, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_rounded_rectangle(ctx, 0, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_rounded_rectangle2(ctx, 0, 0, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_ellipse(ctx, 0, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_elliptic_arc_to(ctx, 0, 0, 0, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_rel_elliptic_arc_to(ctx, 0, 0, 0, 0, 0, 0, 0));
EXPECT_NO_FATAL_FAILURE(vkvg_stroke(ctx));
EXPECT_NO_FATAL_FAILURE(vkvg_stroke_preserve(ctx));
EXPECT_NO_FATAL_FAILURE(vkvg_fill(ctx));
EXPECT_NO_FATAL_FAILURE(vkvg_clip(ctx));
EXPECT_NO_FATAL_FAILURE(vkvg_clip_preserve(ctx));
- EXPECT_NO_FATAL_FAILURE(vkvg_set_opacity(ctx,0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_set_opacity(ctx, 0));
EXPECT_EQ(0, vkvg_get_opacity(ctx));
- EXPECT_NO_FATAL_FAILURE(vkvg_set_source_color(ctx,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_set_source_rgb(ctx,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_set_source_rgba(ctx,0,0,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_set_source_surface(ctx,NULL,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_set_source(ctx,NULL));
- EXPECT_NO_FATAL_FAILURE(vkvg_set_line_width(ctx,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_set_miter_limit(ctx,0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_set_source_color(ctx, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_set_source_rgb(ctx, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_set_source_rgba(ctx, 0, 0, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_set_source_surface(ctx, NULL, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_set_source(ctx, NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_set_line_width(ctx, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_set_miter_limit(ctx, 0));
EXPECT_EQ(0, vkvg_get_miter_limit(ctx));
EXPECT_NO_FATAL_FAILURE(vkvg_set_line_join(ctx, VKVG_LINE_JOIN_MITER));
EXPECT_NO_FATAL_FAILURE(vkvg_set_operator(ctx, VKVG_OPERATOR_OVER));
EXPECT_NO_FATAL_FAILURE(vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD));
- EXPECT_NO_FATAL_FAILURE(vkvg_set_dash(ctx, NULL, 0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_get_dash(ctx, NULL, NULL,NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_set_dash(ctx, NULL, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_get_dash(ctx, NULL, NULL, NULL));
EXPECT_EQ(0, vkvg_get_line_width(ctx));
EXPECT_NO_FATAL_FAILURE(vkvg_save(ctx));
EXPECT_NO_FATAL_FAILURE(vkvg_restore(ctx));
- EXPECT_NO_FATAL_FAILURE(vkvg_translate(ctx,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_scale(ctx,0,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_rotate(ctx,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_transform(ctx,NULL));
- EXPECT_NO_FATAL_FAILURE(vkvg_set_matrix(ctx,NULL));
- EXPECT_NO_FATAL_FAILURE(vkvg_get_matrix(ctx,NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_translate(ctx, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_scale(ctx, 0, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_rotate(ctx, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_transform(ctx, NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_set_matrix(ctx, NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_get_matrix(ctx, NULL));
EXPECT_NO_FATAL_FAILURE(vkvg_identity_matrix(ctx));
- EXPECT_NO_FATAL_FAILURE(vkvg_select_font_face(ctx,NULL));
- EXPECT_NO_FATAL_FAILURE(vkvg_load_font_from_path(ctx,NULL,NULL));
- EXPECT_NO_FATAL_FAILURE(vkvg_load_font_from_memory(ctx,NULL,0,NULL));
- EXPECT_NO_FATAL_FAILURE(vkvg_set_font_size(ctx,0));
- EXPECT_NO_FATAL_FAILURE(vkvg_show_text(ctx,NULL));
- EXPECT_NO_FATAL_FAILURE(vkvg_text_extents(ctx,NULL,NULL));
- EXPECT_NO_FATAL_FAILURE(vkvg_font_extents(ctx,NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_select_font_face(ctx, NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_load_font_from_path(ctx, NULL, NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_load_font_from_memory(ctx, NULL, 0, NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_set_font_size(ctx, 0));
+ EXPECT_NO_FATAL_FAILURE(vkvg_show_text(ctx, NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_text_extents(ctx, NULL, NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_font_extents(ctx, NULL));
- vkvg_text_run_create(ctx,NULL);
- vkvg_text_run_create_with_length(ctx,NULL,10);
+ vkvg_text_run_create(ctx, NULL);
+ vkvg_text_run_create_with_length(ctx, NULL, 10);
- //vkvg_text_run_destroy(NULL);
- vkvg_show_text_run(ctx,NULL);
-}
-#define EXPECT_CP(x,y) { \
- vkvg_get_current_point(ctx, &a, &b);\
- EXPECT_FLOAT_EQ(x, a);\
- EXPECT_FLOAT_EQ(y, b);\
-}
-#define EXPECT_NO_CP() {\
- EXPECT_EQ(false, vkvg_has_current_point(ctx));\
- EXPECT_CP(0,0);\
+ // vkvg_text_run_destroy(NULL);
+ vkvg_show_text_run(ctx, NULL);
}
+#define EXPECT_CP(x, y) \
+ { \
+ vkvg_get_current_point(ctx, &a, &b); \
+ EXPECT_FLOAT_EQ(x, a); \
+ EXPECT_FLOAT_EQ(y, b); \
+ }
+#define EXPECT_NO_CP() \
+ { \
+ EXPECT_EQ(false, vkvg_has_current_point(ctx)); \
+ EXPECT_CP(0, 0); \
+ }
TEST_F(ContextTest, CtxBasicPathCommands) {
- float a = 0.0,b = 0.0,c = 0.0,d = 0.0;
+ float a = 0.0, b = 0.0, c = 0.0, d = 0.0;
VkvgContext ctx = vkvg_create(surf);
EXPECT_NO_CP();
EXPECT_NO_CP();
vkvg_line_to(ctx, 50, 10);
- EXPECT_CP(50,10);
+ EXPECT_CP(50, 10);
vkvg_move_to(ctx, 10, 50);
EXPECT_EQ(true, vkvg_has_current_point(ctx));
- EXPECT_CP(10,50);
+ EXPECT_CP(10, 50);
vkvg_line_to(ctx, 50, 10);
- EXPECT_CP(50,10);
+ EXPECT_CP(50, 10);
vkvg_rel_line_to(ctx, 10, 10);
- EXPECT_CP(60,20);
+ EXPECT_CP(60, 20);
vkvg_close_path(ctx);
EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
vkvg_device_destroy(dev);
- //EXPECT_EQ(0, vkvg_device_get_reference_count(dev));
+ // EXPECT_EQ(0, vkvg_device_get_reference_count(dev));
}
/*TEST(Device, GetVulkanRequirements)
#include "drawTestBase.h"
-//#define STB_IMAGE_IMPLEMENTATION
+// #define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
-//#define STB_IMAGE_WRITE_IMPLEMENTATION
+// #define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
DrawTestBase::DrawTestBase() {
vkvg_device_create_info_t info{};
info.samples = VK_SAMPLE_COUNT_4_BIT;
- dev = vkvg_device_create(&info);
+ dev = vkvg_device_create(&info);
}
-DrawTestBase::~DrawTestBase() {
- vkvg_device_destroy(dev);
-}
+DrawTestBase::~DrawTestBase() { vkvg_device_destroy(dev); }
-void DrawTestBase::SetUp() {
- surf = vkvg_surface_create(dev, 256, 256);
-}
+void DrawTestBase::SetUp() { surf = vkvg_surface_create(dev, 256, 256); }
-void DrawTestBase::TearDown() {
- vkvg_surface_destroy(surf);
-}
+void DrawTestBase::TearDown() { vkvg_surface_destroy(surf); }
void DrawTestBase::compareWithRefImage() {
fs::path targetPath = targetDir / ::testing::UnitTest::GetInstance()->current_test_info()->name();
targetPath.replace_extension(".png");
if (fs::exists(targetPath)) {
- int w = 0, h = 0, channels = 0;
- unsigned char *refImg = stbi_load((char*)targetPath.c_str(), &w, &h, &channels, 4); // force 4 components per pixel
+ int w = 0, h = 0, channels = 0;
+ unsigned char* refImg =
+ stbi_load((char*)targetPath.c_str(), &w, &h, &channels, 4); // force 4 components per pixel
EXPECT_TRUE(refImg != nullptr) << "Could not load image from " << targetPath << stbi_failure_reason();
- EXPECT_EQ(vkvg_surface_get_width(surf),w);
- EXPECT_EQ(vkvg_surface_get_height(surf),h);
+ EXPECT_EQ(vkvg_surface_get_width(surf), w);
+ EXPECT_EQ(vkvg_surface_get_height(surf), h);
- unsigned char *img = (unsigned char*)malloc(w*h*4);
- unsigned char *diffImg = (unsigned char*)malloc(w*h*4);
+ unsigned char* img = (unsigned char*)malloc(w * h * 4);
+ unsigned char* diffImg = (unsigned char*)malloc(w * h * 4);
vkvg_status_t result = vkvg_surface_write_to_memory(surf, img);
EXPECT_EQ(result, VKVG_STATUS_SUCCESS);
uint32_t totDiff = 0;
- for(int y = 0; y < h; y++) {
- for(int x = 0; x < w; x++) {
- unsigned char* refPix = refImg + (y * w + x) * 4;
- unsigned char* pix = img + (y * w + x) * 4;
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ unsigned char* refPix = refImg + (y * w + x) * 4;
+ unsigned char* pix = img + (y * w + x) * 4;
unsigned char* diffPix = diffImg + (y * w + x) * 4;
if (*refPix < *pix)
*diffPix = *pix - *refPix;
GTEST_SKIP() << "Updating reference image: " << targetPath;
}
}
-
-
public:
VkvgDevice dev;
VkvgSurface surf;
- fs::path targetDir;
- fs::path diffDir;
+ fs::path targetDir;
+ fs::path diffDir;
protected:
DrawTestBase();
void compareWithRefImage();
};
-
class ImageDrawTest : public DrawTestBase {
protected:
- fs::path imgPath = fs::path(GTEST_DATA_ROOT) / "mirror2.png";
+ fs::path imgPath = fs::path(GTEST_DATA_ROOT) / "mirror2.png";
VkvgSurface imgSurf;
void SetUp() override {
- surf = vkvg_surface_create(dev, 512, 512);
+ surf = vkvg_surface_create(dev, 512, 512);
imgSurf = vkvg_surface_create_from_image(dev, (char*)imgPath.c_str());
}
void TearDown() override {
EXPECT_EQ(1, vkvg_surface_get_reference_count(surf2));
vkvg_surface_destroy(surf2);
- //EXPECT_EQ(NULL, surf2);
+ // EXPECT_EQ(NULL, surf2);
EXPECT_EQ(devRefCntInit, vkvg_device_get_reference_count(dev));
}
vkvg_set_source_rgb(ctx, 0.5f, 0.5f, 0.5f);
vkvg_paint(ctx);
vkvg_matrix_t mat;
- vkvg_matrix_init_translate(&mat, 142,142);
- vkvg_matrix_rotate(&mat,0.1f);
- vkvg_matrix_init_translate(&mat, -142,-142);
+ vkvg_matrix_init_translate(&mat, 142, 142);
+ vkvg_matrix_rotate(&mat, 0.1f);
+ vkvg_matrix_init_translate(&mat, -142, -142);
vkvg_set_source_surface(ctx, imgSurf, 50, 50);
vkvg_set_matrix(ctx, &mat);
vkvg_set_source_rgb(ctx, 0.5f, 0.5f, 0.5f);
vkvg_paint(ctx);
- fs::path imgPath = fs::path(GTEST_DATA_ROOT) / "mirror2-64.png";
+ fs::path imgPath = fs::path(GTEST_DATA_ROOT) / "mirror2-64.png";
VkvgSurface imgSurf = vkvg_surface_create_from_image(dev, (char*)imgPath.c_str());
vkvg_translate(ctx, 10, 10);
vkvg_set_source_surface(ctx, imgSurf, 0, 0);
vkvg_paint(ctx);
- fs::path imgPath2 = fs::path(GTEST_DATA_ROOT) / "filled.png";
+ fs::path imgPath2 = fs::path(GTEST_DATA_ROOT) / "filled.png";
VkvgSurface imgSurf2 = vkvg_surface_create_from_image(dev, (char*)imgPath2.c_str());
vkvg_set_source_surface(ctx, imgSurf2, 50, 50);
compareWithRefImage();
}
-
#include <gtest/gtest.h>
-int main(int argc, char **argv) {
+int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
// Demonstrate some basic assertions.
TEST(HelloTest, BasicAssertions) {
- // Expect two strings not to be equal.
- EXPECT_STRNE("hello", "world");
- // Expect equality.
- EXPECT_EQ(7 * 6, 42);
+ // Expect two strings not to be equal.
+ EXPECT_STRNE("hello", "world");
+ // Expect equality.
+ EXPECT_EQ(7 * 6, 42);
}
-
-
#include "vkvg.h"
#include <gtest/gtest.h>
-#define CHECK_MAT(_xx,_yx,_xy,_yy,_x0,_y0) \
-EXPECT_FLOAT_EQ (mat.xx, _xx);EXPECT_FLOAT_EQ (mat.yx, _yx);\
-EXPECT_FLOAT_EQ (mat.xy, _xy);EXPECT_FLOAT_EQ (mat.yy, _yy);\
-EXPECT_FLOAT_EQ (mat.x0, _x0);EXPECT_FLOAT_EQ (mat.y0, _y0);
-
+#define CHECK_MAT(_xx, _yx, _xy, _yy, _x0, _y0) \
+ EXPECT_FLOAT_EQ(mat.xx, _xx); \
+ EXPECT_FLOAT_EQ(mat.yx, _yx); \
+ EXPECT_FLOAT_EQ(mat.xy, _xy); \
+ EXPECT_FLOAT_EQ(mat.yy, _yy); \
+ EXPECT_FLOAT_EQ(mat.x0, _x0); \
+ EXPECT_FLOAT_EQ(mat.y0, _y0);
TEST(MatrixTest, MatixInit) {
- vkvg_matrix_t mat = {1,0,0,1,0,0};
- CHECK_MAT(1,0,0,1,0,0);
+ vkvg_matrix_t mat = {1, 0, 0, 1, 0, 0};
+ CHECK_MAT(1, 0, 0, 1, 0, 0);
vkvg_matrix_init_identity(&mat);
- CHECK_MAT(1,0,0,1,0,0);
+ CHECK_MAT(1, 0, 0, 1, 0, 0);
vkvg_matrix_init(&mat, 1.3f, 2.5f, 0.3f, 0.7f, 1.2f, 1.7f);
CHECK_MAT(1.3f, 2.5f, 0.3f, 0.7f, 1.2f, 1.7f);
- float a,b;
+ float a, b;
vkvg_matrix_init_translate(&mat, 1.3f, 2.5f);
- CHECK_MAT(1,0,0,1,1.3f,2.5f);
+ CHECK_MAT(1, 0, 0, 1, 1.3f, 2.5f);
vkvg_matrix_init_scale(&mat, 2.1f, 1.5f);
- CHECK_MAT(2.1f,0,0,1.5f,0,0);
+ CHECK_MAT(2.1f, 0, 0, 1.5f, 0, 0);
vkvg_matrix_get_scale(&mat, &a, &b);
- EXPECT_FLOAT_EQ(a,2.1f);
- EXPECT_FLOAT_EQ(b,1.5f);
+ EXPECT_FLOAT_EQ(a, 2.1f);
+ EXPECT_FLOAT_EQ(b, 1.5f);
vkvg_matrix_init_rotate(&mat, 2.f);
- CHECK_MAT(cosf(2.f),sinf(2.f),-sinf(2.f),cosf(2.f),0,0);
+ CHECK_MAT(cosf(2.f), sinf(2.f), -sinf(2.f), cosf(2.f), 0, 0);
}
TEST(MatrixTest, MatixOperation) {
- vkvg_matrix_t mat = {0,0,0,0,0,0};
- //TODO
-
+ vkvg_matrix_t mat = {0, 0, 0, 0, 0, 0};
+ // TODO
}
TEST(MatrixTest, MatixIvert) {
- vkvg_matrix_t mat = {0,0,0,0,0,0};
+ vkvg_matrix_t mat = {0, 0, 0, 0, 0, 0};
vkvg_status_t res = vkvg_matrix_invert(&mat);
- EXPECT_EQ(res,VKVG_STATUS_INVALID_MATRIX);
+ EXPECT_EQ(res, VKVG_STATUS_INVALID_MATRIX);
- mat = {1,1,0,0,0,0};
+ mat = {1, 1, 0, 0, 0, 0};
res = vkvg_matrix_invert(&mat);
- EXPECT_EQ(res,VKVG_STATUS_INVALID_MATRIX);
+ EXPECT_EQ(res, VKVG_STATUS_INVALID_MATRIX);
- mat = {1,0,0,1,0,0};
+ mat = {1, 0, 0, 1, 0, 0};
res = vkvg_matrix_invert(&mat);
- EXPECT_EQ(res,VKVG_STATUS_SUCCESS);
- CHECK_MAT(1,0,0,1,0,0);
+ EXPECT_EQ(res, VKVG_STATUS_SUCCESS);
+ CHECK_MAT(1, 0, 0, 1, 0, 0);
vkvg_matrix_init_scale(&mat, 2.1f, 1.5f);
res = vkvg_matrix_invert(&mat);
- EXPECT_EQ(res,VKVG_STATUS_SUCCESS);
- CHECK_MAT(1.f/2.1f,0,0,1.f/1.5f,0,0);
+ EXPECT_EQ(res, VKVG_STATUS_SUCCESS);
+ CHECK_MAT(1.f / 2.1f, 0, 0, 1.f / 1.5f, 0, 0);
vkvg_matrix_init_translate(&mat, 2.1f, 1.5f);
res = vkvg_matrix_invert(&mat);
- EXPECT_EQ(res,VKVG_STATUS_SUCCESS);
- CHECK_MAT(1,0,0,1,-2.1f,-1.5f);
+ EXPECT_EQ(res, VKVG_STATUS_SUCCESS);
+ CHECK_MAT(1, 0, 0, 1, -2.1f, -1.5f);
vkvg_matrix_init_rotate(&mat, 2.f);
res = vkvg_matrix_invert(&mat);
- EXPECT_EQ(res,VKVG_STATUS_SUCCESS);
- CHECK_MAT(cosf(2.f),-sinf(2.f),sinf(2.f),cosf(2.f),0,0);
-
-
+ EXPECT_EQ(res, VKVG_STATUS_SUCCESS);
+ CHECK_MAT(cosf(2.f), -sinf(2.f), sinf(2.f), cosf(2.f), 0, 0);
}
class PatternDrawTest : public DrawTestBase {
protected:
- fs::path imgPath = fs::path(GTEST_DATA_ROOT) / "mirror2.png";
+ fs::path imgPath = fs::path(GTEST_DATA_ROOT) / "mirror2.png";
VkvgSurface imgSurf;
void SetUp() override {
- surf = vkvg_surface_create(dev, 512, 512);
+ surf = vkvg_surface_create(dev, 512, 512);
imgSurf = vkvg_surface_create_from_image(dev, (char*)imgPath.c_str());
}
void TearDown() override {
VkvgPattern pat = vkvg_pattern_create_for_surface(NULL);
EXPECT_EQ(VKVG_STATUS_NULL_POINTER, vkvg_pattern_status(pat));
- pat = vkvg_pattern_create_linear(0,0,0,0);
+ pat = vkvg_pattern_create_linear(0, 0, 0, 0);
EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_pattern_status(pat));
EXPECT_EQ(1, vkvg_pattern_get_reference_count(pat));
vkvg_pattern_reference(pat);
vkvg_pattern_destroy(pat);
EXPECT_EQ(1, vkvg_pattern_get_reference_count(pat));
vkvg_pattern_destroy(pat);
- //EXPECT_EQ(NULL, pat);
+ // EXPECT_EQ(NULL, pat);
}
TEST_F(PatternDrawTest, PaintPattern) {
#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
};
#include <stdlib.h>
-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_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
#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
#ifdef STBI_WINDOWS_UTF8
-STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
+STBIDEF int stbi_convert_wchar_to_utf8(char* buffer, size_t bufferlen, const wchar_t* input);
#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_from_file_16(FILE *f, 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
// on most compilers (and ALL modern mainstream compilers) this is 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(const char *buffer, int len, int *outlen);
-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 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(const char* buffer, int len, int* outlen);
+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);
#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_EXTERN extern
#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
+#endif
#else
- #define stbi_inline __forceinline
+#define stbi_inline __forceinline
#endif
#ifndef STBI_NO_THREAD_LOCALS
- #if defined(__cplusplus) && __cplusplus >= 201103L
- #define STBI_THREAD_LOCAL thread_local
- #elif defined(__GNUC__) && __GNUC__ < 5
- #define STBI_THREAD_LOCAL __thread
- #elif defined(_MSC_VER)
- #define STBI_THREAD_LOCAL __declspec(thread)
- #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
- #define STBI_THREAD_LOCAL _Thread_local
- #endif
-
- #ifndef STBI_THREAD_LOCAL
- #if defined(__GNUC__)
- #define STBI_THREAD_LOCAL __thread
- #endif
- #endif
+#if defined(__cplusplus) && __cplusplus >= 201103L
+#define STBI_THREAD_LOCAL thread_local
+#elif defined(__GNUC__) && __GNUC__ < 5
+#define STBI_THREAD_LOCAL __thread
+#elif defined(_MSC_VER)
+#define STBI_THREAD_LOCAL __declspec(thread)
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
+#define STBI_THREAD_LOCAL _Thread_local
+#endif
+
+#ifndef STBI_THREAD_LOCAL
+#if defined(__GNUC__)
+#define STBI_THREAD_LOCAL __thread
+#endif
+#endif
#endif
#if defined(_MSC_VER) || defined(__SYMBIAN32__)
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;
#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) >> (-(y) & 31)))
+#define stbi_lrot(x, y) (((x) << (y)) | ((x) >> (-(y) & 31)))
#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
#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2)
-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;
}
#endif
#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2)
-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
// 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 callback_already_read;
+ int read_from_callbacks;
+ int buflen;
+ stbi_uc buffer_start[128];
+ int callback_already_read;
- 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);
+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->callback_already_read = 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->callback_already_read = 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->callback_already_read = 0;
- s->img_buffer = 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->callback_already_read = 0;
+ s->img_buffer = 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)
-{
- int ch;
- fseek((FILE*) user, n, SEEK_CUR);
- ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */
- if (ch != EOF) {
- ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */
- }
+static void stbi__stdio_skip(void* user, int n) {
+ int ch;
+ fseek((FILE*)user, n, SEEK_CUR);
+ ch = fgetc((FILE*)user); /* have to read a byte to reset feof()'s flag */
+ if (ch != EOF) {
+ ungetc(ch, (FILE*)user); /* push byte back onto stream if valid. */
+ }
}
-static int stbi__stdio_eof(void *user)
-{
- return feof((FILE*) user) || ferror((FILE *) user);
-}
+static int stbi__stdio_eof(void* user) { return feof((FILE*)user) || ferror((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_is16(stbi__context *s);
+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_is16(stbi__context* s);
#endif
static
#ifdef STBI_THREAD_LOCAL
-STBI_THREAD_LOCAL
+ STBI_THREAD_LOCAL
#endif
-const char *stbi__g_failure_reason;
+ 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; }
#ifndef STBI_NO_FAILURE_STRINGS
-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;
}
#endif
-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;
}
#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
// 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);
}
#endif
// 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) || !defined(STBI_NO_PNM)
-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
#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
// 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);
}
#endif
-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) || !defined(STBI_NO_PNM)
-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
// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow.
-static int stbi__addints_valid(int a, int b)
-{
- if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow
- if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0.
- return a <= INT_MAX - b;
+static int stbi__addints_valid(int a, int b) {
+ if ((a >= 0) != (b >= 0))
+ return 1; // a and b have different signs, so no overflow
+ if (a < 0 && b < 0)
+ return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0.
+ return a <= INT_MAX - b;
}
// returns 1 if the product of two ints fits in a signed short, 0 on overflow.
-static int stbi__mul2shorts_valid(int a, int b)
-{
- if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow
- if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid
- if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN
- return a >= SHRT_MIN / b;
+static int stbi__mul2shorts_valid(int a, int b) {
+ if (b == 0 || b == -1)
+ return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow
+ if ((a >= 0) == (b >= 0))
+ return a <= SHRT_MAX / b; // product is positive, so similar to mul2sizes_valid
+ if (b < 0)
+ return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN
+ return a >= SHRT_MIN / b;
}
// stbi__err - error
// 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_global = 0;
-STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
-{
- stbi__vertically_flip_on_load_global = flag_true_if_should_flip;
+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) {
+ stbi__vertically_flip_on_load_global = flag_true_if_should_flip;
}
#ifndef STBI_THREAD_LOCAL
-#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global
+#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global
#else
static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set;
-STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip)
-{
- stbi__vertically_flip_on_load_local = flag_true_if_should_flip;
- stbi__vertically_flip_on_load_set = 1;
+STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) {
+ stbi__vertically_flip_on_load_local = flag_true_if_should_flip;
+ stbi__vertically_flip_on_load_set = 1;
}
-#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \
- ? stbi__vertically_flip_on_load_local \
- : stbi__vertically_flip_on_load_global)
+#define stbi__vertically_flip_on_load \
+ (stbi__vertically_flip_on_load_set ? stbi__vertically_flip_on_load_local : stbi__vertically_flip_on_load_global)
#endif // STBI_THREAD_LOCAL
-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;
-
- // test the formats with a very explicit header first (at least a FOURCC
- // or distinctive magic number first)
- #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);
- #else
- STBI_NOTUSED(bpc);
- #endif
- #ifndef STBI_NO_PIC
- if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri);
- #endif
-
- // then the formats that can end up attempting to load with just 1 or 2
- // bytes matching expectations; these are prone to false positives, so
- // try them later
- #ifndef STBI_NO_JPEG
- if (stbi__jpeg_test(s)) return stbi__jpeg_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;
+
+// test the formats with a very explicit header first (at least a FOURCC
+// or distinctive magic number first)
+#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);
+#else
+ STBI_NOTUSED(bpc);
+#endif
+#ifndef STBI_NO_PIC
+ if (stbi__pic_test(s))
+ return stbi__pic_load(s, x, y, comp, req_comp, ri);
+#endif
+
+// then the formats that can end up attempting to load with just 1 or 2
+// bytes matching expectations; these are prone to false positives, so
+// try them later
+#ifndef STBI_NO_JPEG
+ if (stbi__jpeg_test(s))
+ return stbi__jpeg_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
- reduced = (stbi_uc *) stbi__malloc(img_len);
- if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory");
+#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 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");
+
+ 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;
}
-#ifndef STBI_NO_GIF
-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 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;
+ }
+ }
+}
- stbi_uc *bytes = (stbi_uc *)image;
- for (slice = 0; slice < z; ++slice) {
- stbi__vertical_flip(bytes, w, h, bytes_per_pixel);
- bytes += slice_size;
- }
+#ifndef STBI_NO_GIF
+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;
+ }
}
#endif
-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 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;
- // it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
- STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
+ // it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
+ STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
- if (ri.bits_per_channel != 8) {
- 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) {
+ 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;
- // it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
- STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
+ // it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
+ STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
- if (ri.bits_per_channel != 16) {
- 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) {
+ 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
#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)
-STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
-STBI_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);
+STBI_EXTERN
+ __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char* str,
+ int cbmb, wchar_t* widestr, int cchwide);
+STBI_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);
#endif
#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)
-STBIDEF int stbi_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);
+STBIDEF int stbi_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 *stbi__fopen(char const *filename, char const *mode)
-{
- FILE *f;
+static FILE* stbi__fopen(char const* filename, char const* mode) {
+ FILE* f;
#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)
- wchar_t wMode[64];
- wchar_t wFilename[1024];
- if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
- return 0;
+ wchar_t wMode[64];
+ wchar_t wFilename[1024];
+ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename) / sizeof(*wFilename)))
+ return 0;
- if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
- return 0;
+ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode) / sizeof(*wMode)))
+ return 0;
#if defined(_MSC_VER) && _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;
}
+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);
+
+ 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;
+ 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
-};
+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);
+ s->callback_already_read += (int)(s->img_buffer - s->img_buffer_original);
+ 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;
+ }
+}
-static void stbi__refill_buffer(stbi__context *s)
-{
- int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
- s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original);
- 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 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;
}
#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
-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;
- }
+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;
+ return s->img_buffer >= s->img_buffer_end;
}
#endif
-#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC)
+#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && \
+ defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC)
// nothing
#else
-static void stbi__skip(stbi__context *s, int n)
-{
- if (n == 0) return; // already there!
- 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 void stbi__skip(stbi__context* s, int n) {
+ if (n == 0)
+ return; // already there!
+ 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;
}
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM)
// nothing
#else
-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;
- }
- }
+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;
+ if (s->img_buffer + n <= s->img_buffer_end) {
+ memcpy(buffer, s->img_buffer, n);
+ s->img_buffer += n;
+ return 1;
+ } else
+ return 0;
}
#endif
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
// nothing
#else
-static int stbi__get16be(stbi__context *s)
-{
- int z = stbi__get8(s);
- return (z << 8) + stbi__get8(s);
+static int stbi__get16be(stbi__context* s) {
+ int z = stbi__get8(s);
+ return (z << 8) + stbi__get8(s);
}
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
// nothing
#else
-static stbi__uint32 stbi__get32be(stbi__context *s)
-{
- stbi__uint32 z = stbi__get16be(s);
- return (z << 16) + stbi__get16be(s);
+static stbi__uint32 stbi__get32be(stbi__context* s) {
+ stbi__uint32 z = stbi__get16be(s);
+ return (z << 16) + stbi__get16be(s);
}
#endif
#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);
- z += (stbi__uint32)stbi__get16le(s) << 16;
- return z;
+static stbi__uint32 stbi__get32le(stbi__context* s) {
+ stbi__uint32 z = stbi__get16le(s);
+ z += (stbi__uint32)stbi__get16le(s) << 16;
+ return z;
}
#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
-#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
+#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && \
+ defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
//////////////////////////////////////////////////////////////////////////////
// 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 stbi_uc stbi__compute_y(int r, int g, int b) { return (stbi_uc)(((r * 77) + (g * 150) + (29 * b)) >> 8); }
#endif
-#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
+#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && \
+ defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
-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); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion");
- }
- #undef STBI__CASE
- }
-
- STBI_FREE(data);
- return good;
+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);
+ STBI_FREE(data);
+ STBI_FREE(good);
+ return stbi__errpuc("unsupported", "Unsupported format conversion");
+ }
+#undef STBI__CASE
+ }
+
+ STBI_FREE(data);
+ return good;
}
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
// nothing
#else
-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__compute_y_16(int r, int g, int b) {
+ return (stbi__uint16)(((r * 77) + (g * 150) + (29 * b)) >> 8);
}
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
// nothing
#else
-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); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion");
- }
- #undef STBI__CASE
- }
-
- STBI_FREE(data);
- return good;
+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);
+ STBI_FREE(data);
+ STBI_FREE(good);
+ return (stbi__uint16*)stbi__errpuc("unsupported", "Unsupported format conversion");
+ }
+#undef STBI__CASE
+ }
+
+ STBI_FREE(data);
+ return good;
}
#endif
#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 (n < comp) {
- for (i=0; i < x*y; ++i) {
- output[i*comp + n] = data[i*comp + n]/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 (n < comp) {
+ for (i = 0; i < x * y; ++i) {
+ output[i * comp + n] = data[i * comp + n] / 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;
-}
-#endif
-
+#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
+
//////////////////////////////////////////////////////////////////////////////
//
// "baseline" JPEG/JFIF decoder
#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);
- if(k >= 257) return stbi__err("bad size list","Corrupt JPEG");
- }
- }
- 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);
+ if (k >= 257)
+ return stbi__err("bad size list", "Corrupt JPEG");
+ }
+ }
+ 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];
- if(c < 0 || c >= 256) // symbol id out of bounds!
- return -1;
- 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];
+ if (c < 0 || c >= 256) // symbol id out of bounds!
+ return -1;
+ 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);
- if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
-
- sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative)
- 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__jbias[n] & (sgn - 1));
+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);
+ if (j->code_bits < n)
+ return 0; // ran out of bits from stream, return 0s intead of continuing
+
+ sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative)
+ 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__jbias[n] & (sgn - 1));
}
// 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);
- if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
- 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);
- if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing
- 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);
+ if (j->code_bits < n)
+ return 0; // ran out of bits from stream, return 0s intead of continuing
+ 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);
+ if (j->code_bits < 1)
+ return 0; // ran out of bits from stream, return 0s intead of continuing
+ 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 || t > 15) 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;
- if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG");
- dc = j->img_comp[b].dc_pred + diff;
- j->img_comp[b].dc_pred = dc;
- if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
- 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
- if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
- 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);
- if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
- diff = t ? stbi__extend_receive(j, t) : 0;
-
- if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG");
- dc = j->img_comp[b].dc_pred + diff;
- j->img_comp[b].dc_pred = dc;
- if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
- data[0] = (short) (dc * (1 << 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
+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 || t > 15)
+ 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;
+ if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff))
+ return stbi__err("bad delta", "Corrupt JPEG");
+ dc = j->img_comp[b].dc_pred + diff;
+ j->img_comp[b].dc_pred = dc;
+ if (!stbi__mul2shorts_valid(dc, dequant[0]))
+ return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+ 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
- if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
+ s = r & 15; // combined length
+ if (s > j->code_bits)
+ return stbi__err("bad huffman code", "Combined length longer than code bits available");
j->code_buffer <<= s;
j->code_bits -= s;
- zig = stbi__jpeg_dezigzag[k++];
- data[zig] = (short) ((r >> 8) * (1 << shift));
- } else {
+ // 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");
+ 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;
+ if (rs != 0xf0)
+ break; // end block
+ k += 16;
} else {
- k += r;
- zig = stbi__jpeg_dezigzag[k++];
- data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift));
+ k += r;
+ // decode into unzigzag'd location
+ zig = stbi__jpeg_dezigzag[k++];
+ data[zig] = (short)(stbi__extend_receive(j, s) * dequant[zig]);
}
- }
- } 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
- }
+ }
+ } 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);
+ if (t < 0 || t > 15)
+ return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+ diff = t ? stbi__extend_receive(j, t) : 0;
+
+ if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff))
+ return stbi__err("bad delta", "Corrupt JPEG");
+ dc = j->img_comp[b].dc_pred + diff;
+ j->img_comp[b].dc_pred = dc;
+ if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low))
+ return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+ data[0] = (short)(dc * (1 << 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
+ if (s > j->code_bits)
+ return stbi__err("bad huffman code", "Combined length longer than code bits available");
+ j->code_buffer <<= s;
+ j->code_bits -= s;
+ zig = stbi__jpeg_dezigzag[k++];
+ data[zig] = (short)((r >> 8) * (1 << shift));
} 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;
+ 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) * (1 << shift));
+ }
}
-
- // 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);
+ } 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;
+ }
}
- } while (k <= j->spec_end);
- }
- }
- return 1;
+ } 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);
- }
+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 {
- 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;
+ 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 { // 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);
+ 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;
- }
- }
- }
- // 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 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;
- }
- }
-}
-
-static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant)
-{
- int i;
- for (i=0; i < 64; ++i)
- data[i] *= dequant[i];
+ 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_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 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) {
+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));
+ 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];
+ }
+ 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];
}
- if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values!
+ if (n > 256)
+ return stbi__err("bad DHT header", "Corrupt JPEG"); // Loop over i < n would write past end of values!
L -= 17;
if (tc == 0) {
- if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0;
- v = z->huff_dc[th].values;
+ 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;
+ 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);
+ 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);
+ 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
+ }
+ 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;
- }
+ stbi__skip(z->s, L);
+ return 1;
+ }
- return stbi__err("unknown marker","Corrupt JPEG");
+ 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
- if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
- if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
- 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;
- }
-
- // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios
- // and I've never seen a non-corrupted JPEG file actually use them
- for (i=0; i < s->img_n; ++i) {
- if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG");
- if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG");
- }
-
- // 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;
}
-// 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)
+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
+ if (s->img_y > STBI_MAX_DIMENSIONS)
+ return stbi__err("too large", "Very large image (corrupt?)");
+ if (s->img_x > STBI_MAX_DIMENSIONS)
+ return stbi__err("too large", "Very large image (corrupt?)");
+ 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;
+ }
-#define stbi__SOF_progressive(x) ((x) == 0xc2)
+ 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");
+ }
-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;
-}
-
-static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
-{
- // some JPEGs have junk at end, skip over it but if we find what looks
- // like a valid marker, resume there
- while (!stbi__at_eof(j->s)) {
- stbi_uc x = stbi__get8(j->s);
- while (x == 0xff) { // might be a marker
- if (stbi__at_eof(j->s)) return STBI__MARKER_none;
- x = stbi__get8(j->s);
- if (x != 0x00 && x != 0xff) {
- // not a stuffed zero or lead-in to another marker, looks
- // like an actual marker, return it
- return x;
- }
- // stuffed zero has x=0 now which ends the loop, meaning we go
- // back to regular scan loop.
- // repeated 0xff keeps trying to read the next byte of the marker.
- }
- }
- return STBI__MARKER_none;
+ 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;
+ }
+
+ // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios
+ // and I've never seen a non-corrupted JPEG file actually use them
+ for (i = 0; i < s->img_n; ++i) {
+ if (h_max % z->img_comp[i].h != 0)
+ return stbi__err("bad H", "Corrupt JPEG");
+ if (v_max % z->img_comp[i].v != 0)
+ return stbi__err("bad V", "Corrupt JPEG");
+ }
+
+ // 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;
+}
+
+static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg* j) {
+ // some JPEGs have junk at end, skip over it but if we find what looks
+ // like a valid marker, resume there
+ while (!stbi__at_eof(j->s)) {
+ stbi_uc x = stbi__get8(j->s);
+ while (x == 0xff) { // might be a marker
+ if (stbi__at_eof(j->s))
+ return STBI__MARKER_none;
+ x = stbi__get8(j->s);
+ if (x != 0x00 && x != 0xff) {
+ // not a stuffed zero or lead-in to another marker, looks
+ // like an actual marker, return it
+ return x;
+ }
+ // stuffed zero has x=0 now which ends the loop, meaning we go
+ // back to regular scan loop.
+ // repeated 0xff keeps trying to read the next byte of the marker.
+ }
+ }
+ return STBI__MARKER_none;
}
// 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 ) {
- j->marker = stbi__skip_jpeg_junk_at_end(j);
- // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0
- }
- m = stbi__get_marker(j);
- if (STBI__RESTART(m))
+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) {
+ j->marker = stbi__skip_jpeg_junk_at_end(j);
+ // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually
+ // return 0
+ }
+ m = stbi__get_marker(j);
+ if (STBI__RESTART(m))
+ m = stbi__get_marker(j);
+ } 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");
m = stbi__get_marker(j);
- } 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");
- m = stbi__get_marker(j);
- } else {
- if (!stbi__process_marker(j, m)) return 1;
- m = stbi__get_marker(j);
- }
- }
- if (j->progressive)
- stbi__jpeg_finish(j);
- return 1;
+ } else {
+ if (!stbi__process_marker(j, m))
+ return 1;
+ 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);
-#endif
-
- // "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);
-
- 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);
-
- 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;
+ // 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];
+ }
+
+ 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);
+
+ STBI_NOTUSED(hs);
+
+ 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;
}
// 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;
- }
- }
-#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;
- }
+ // 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;
+ }
}
#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 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;
-
- // nothing to do if no components requested; check this now to avoid
- // accessing uninitialized coutput[0] later
- if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; }
-
- // resample and color-convert
- {
- int k;
- unsigned int i,j;
- stbi_uc *output;
- stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL };
-
- 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;
+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;
+
+ // nothing to do if no components requested; check this now to avoid
+ // accessing uninitialized coutput[0] later
+ if (decode_n <= 0) {
+ stbi__cleanup_jpeg(z);
+ return NULL;
+ }
+
+ // resample and color-convert
+ {
+ int k;
+ unsigned int i, j;
+ stbi_uc* output;
+ stbi_uc* coutput[4] = {NULL, NULL, NULL, NULL};
+
+ 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");
}
- }
- 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;
- }
+
+ 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 {
- 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; }
+ 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;
- }
+ }
+ 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));
- if (!j) return stbi__errpuc("outofmem", "Out of memory");
- memset(j, 0, 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));
- if (!j) return stbi__err("outofmem", "Out of memory");
- memset(j, 0, 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 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));
+ if (!j)
+ return stbi__errpuc("outofmem", "Out of memory");
+ memset(j, 0, 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_info(stbi__context *s, int *x, int *y, int *comp)
-{
- int result;
- stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
- if (!j) return stbi__err("outofmem", "Out of memory");
- memset(j, 0, sizeof(stbi__jpeg));
- j->s = s;
- result = stbi__jpeg_info_raw(j, x, y, 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));
+ if (!j)
+ return stbi__err("outofmem", "Out of memory");
+ memset(j, 0, 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)));
+ if (!j)
+ return stbi__err("outofmem", "Out of memory");
+ memset(j, 0, 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__ZNSYMS 288 // number of symbols in literal/length alphabet
+#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables
+#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1)
+#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet
// 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[STBI__ZNSYMS];
- stbi__uint16 value[STBI__ZNSYMS];
+typedef struct {
+ stbi__uint16 fast[1 << STBI__ZFAST_BITS];
+ stbi__uint16 firstcode[16];
+ int maxcode[17];
+ stbi__uint16 firstsymbol[16];
+ stbi_uc size[STBI__ZNSYMS];
+ stbi__uint16 value[STBI__ZNSYMS];
} 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);
+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;
+ ++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;
- int hit_zeof_once;
- stbi__uint32 code_buffer;
+typedef struct {
+ stbi_uc * zbuffer, *zbuffer_end;
+ int num_bits;
+ int hit_zeof_once;
+ 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 int stbi__zeof(stbi__zbuf *z)
-{
- return (z->zbuffer >= z->zbuffer_end);
+stbi_inline static int stbi__zeof(stbi__zbuf* z) { return (z->zbuffer >= z->zbuffer_end); }
+
+stbi_inline static stbi_uc stbi__zget8(stbi__zbuf* z) { return stbi__zeof(z) ? 0 : *z->zbuffer++; }
+
+static void stbi__fill_bits(stbi__zbuf* z) {
+ do {
+ if (z->code_buffer >= (1U << z->num_bits)) {
+ z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */
+ return;
+ }
+ 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];
+ if (b >= STBI__ZNSYMS)
+ return -1; // some data was corrupt somewhere!
+ if (z->size[b] != s)
+ return -1; // was originally an assert, but report failure instead.
+ 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) {
+ if (stbi__zeof(a)) {
+ if (!a->hit_zeof_once) {
+ // This is the first time we hit eof, insert 16 extra padding btis
+ // to allow us to keep going; if we actually consume any of them
+ // though, that is invalid data. This is caught later.
+ a->hit_zeof_once = 1;
+ a->num_bits += 16; // add 16 implicit zero bits
+ } else {
+ // We already inserted our extra 16 padding bits and are again
+ // out, this stream is actually prematurely terminated.
+ return -1;
+ }
+ } else {
+ 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;
+ unsigned int cur, limit, old_limit;
+ z->zout = zout;
+ if (!z->z_expandable)
+ return stbi__err("output buffer limit", "Corrupt PNG");
+ cur = (unsigned int)(z->zout - z->zout_start);
+ limit = old_limit = (unsigned)(z->zout_end - z->zout_start);
+ if (UINT_MAX - cur < (unsigned)n)
+ return stbi__err("outofmem", "Out of memory");
+ while (cur + n > limit) {
+ if (limit > UINT_MAX / 2)
+ return stbi__err("outofmem", "Out of memory");
+ 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;
+ if (a->hit_zeof_once && a->num_bits < 16) {
+ // The first time we hit zeof, we inserted 16 extra zero bits into our bit
+ // buffer so the decoder can just do its speculative decoding. But if we
+ // actually consumed any of those bits (which is the case when num_bits < 16),
+ // the stream actually read past the end so it is malformed.
+ return stbi__err("unexpected end", "Corrupt PNG");
+ }
+ return 1;
+ }
+ if (z >= 286)
+ return stbi__err(
+ "bad huffman code",
+ "Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data
+ 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 || z >= 30)
+ return stbi__err(
+ "bad huffman code",
+ "Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data
+ 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 (len > a->zout_end - zout) {
+ 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);
+ }
+ }
+ }
+ }
}
-stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)
-{
- return stbi__zeof(z) ? 0 : *z->zbuffer++;
-}
+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;
-static void stbi__fill_bits(stbi__zbuf *z)
-{
- do {
- if (z->code_buffer >= (1U << z->num_bits)) {
- z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */
- return;
- }
- z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;
- z->num_bits += 8;
- } while (z->num_bits <= 24);
-}
+ 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;
-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;
-}
+ 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;
-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];
- if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere!
- if (z->size[b] != s) return -1; // was originally an assert, but report failure instead.
- 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) {
- if (stbi__zeof(a)) {
- if (!a->hit_zeof_once) {
- // This is the first time we hit eof, insert 16 extra padding btis
- // to allow us to keep going; if we actually consume any of them
- // though, that is invalid data. This is caught later.
- a->hit_zeof_once = 1;
- a->num_bits += 16; // add 16 implicit zero bits
- } else {
- // We already inserted our extra 16 padding bits and are again
- // out, this stream is actually prematurely terminated.
- return -1;
- }
- } else {
- 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;
- unsigned int cur, limit, old_limit;
- z->zout = zout;
- if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
- cur = (unsigned int) (z->zout - z->zout_start);
- limit = old_limit = (unsigned) (z->zout_end - z->zout_start);
- if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory");
- while (cur + n > limit) {
- if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory");
- 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;
- if (a->hit_zeof_once && a->num_bits < 16) {
- // The first time we hit zeof, we inserted 16 extra zero bits into our bit
- // buffer so the decoder can just do its speculative decoding. But if we
- // actually consumed any of those bits (which is the case when num_bits < 16),
- // the stream actually read past the end so it is malformed.
- return stbi__err("unexpected end","Corrupt PNG");
- }
- return 1;
- }
- if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data
- 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 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data
- 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 (len > a->zout_end - zout) {
- 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 if (c == 18) {
- c = stbi__zreceive(a,7)+11;
- } else {
+ 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 (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;
- }
- if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG");
- // 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 (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
- 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[STBI__ZNSYMS] =
-{
- 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
-};
+ 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 if (c == 18) {
+ c = stbi__zreceive(a, 7) + 11;
+ } else {
+ return stbi__err("bad codelengths", "Corrupt PNG");
+ }
+ 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;
+ }
+ if (a->num_bits < 0)
+ return stbi__err("zlib corrupt", "Corrupt PNG");
+ // 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 (stbi__zeof(a))
+ return stbi__err("bad zlib header", "Corrupt PNG"); // zlib spec
+ 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[STBI__ZNSYMS] = {
+ 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;
- a->hit_zeof_once = 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 , STBI__ZNSYMS)) 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;
+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;
+ a->hit_zeof_once = 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, STBI__ZNSYMS))
+ 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;
+ }
+}
- return stbi__parse_zlib(a, parse_header);
+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(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 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 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 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;
+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 filter used for first scanline to avoid needing a dummy row of 0s
- STBI__F_avg_first
+ STBI__F_none = 0,
+ STBI__F_sub = 1,
+ STBI__F_up = 2,
+ STBI__F_avg = 3,
+ STBI__F_paeth = 4,
+ // synthetic filter used for first scanline to avoid needing a dummy row of 0s
+ STBI__F_avg_first
};
-static stbi_uc first_row_filter[5] =
-{
- STBI__F_none,
- STBI__F_sub,
- STBI__F_none,
- STBI__F_avg_first,
- STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub
+static stbi_uc first_row_filter[5] = {
+ STBI__F_none, STBI__F_sub, STBI__F_none, STBI__F_avg_first,
+ STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub
};
-static int stbi__paeth(int a, int b, int c)
-{
- // This formulation looks very different from the reference in the PNG spec, but is
- // actually equivalent and has favorable data dependencies and admits straightforward
- // generation of branch-free code, which helps performance significantly.
- int thresh = c*3 - (a + b);
- int lo = a < b ? a : b;
- int hi = a < b ? b : a;
- int t0 = (hi <= thresh) ? lo : c;
- int t1 = (thresh <= lo) ? hi : t0;
- return t1;
+static int stbi__paeth(int a, int b, int c) {
+ // This formulation looks very different from the reference in the PNG spec, but is
+ // actually equivalent and has favorable data dependencies and admits straightforward
+ // generation of branch-free code, which helps performance significantly.
+ int thresh = c * 3 - (a + b);
+ int lo = a < b ? a : b;
+ int hi = a < b ? b : a;
+ int t0 = (hi <= thresh) ? lo : c;
+ int t1 = (thresh <= lo) ? hi : t0;
+ return t1;
}
-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};
// adds an extra all-255 alpha channel
// dest == src is legal
// img_n must be 1 or 3
-static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n)
-{
- int i;
- // must process data backwards since we allow dest==src
- if (img_n == 1) {
- for (i=x-1; i >= 0; --i) {
- dest[i*2+1] = 255;
- dest[i*2+0] = src[i];
- }
- } else {
- STBI_ASSERT(img_n == 3);
- for (i=x-1; i >= 0; --i) {
- dest[i*4+3] = 255;
- dest[i*4+2] = src[i*3+2];
- dest[i*4+1] = src[i*3+1];
- dest[i*4+0] = src[i*3+0];
- }
- }
+static void stbi__create_png_alpha_expand8(stbi_uc* dest, stbi_uc* src, stbi__uint32 x, int img_n) {
+ int i;
+ // must process data backwards since we allow dest==src
+ if (img_n == 1) {
+ for (i = x - 1; i >= 0; --i) {
+ dest[i * 2 + 1] = 255;
+ dest[i * 2 + 0] = src[i];
+ }
+ } else {
+ STBI_ASSERT(img_n == 3);
+ for (i = x - 1; i >= 0; --i) {
+ dest[i * 4 + 3] = 255;
+ dest[i * 4 + 2] = src[i * 3 + 2];
+ dest[i * 4 + 1] = src[i * 3 + 1];
+ dest[i * 4 + 0] = src[i * 3 + 0];
+ }
+ }
}
// 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;
- stbi_uc *filter_buf;
- int all_ok = 1;
- 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");
-
- // note: error exits here don't need to clean up a->out individually,
- // stbi__do_png always does on error.
- 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);
- if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG");
- 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");
-
- // Allocate two scan lines worth of filter workspace buffer.
- filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0);
- if (!filter_buf) return stbi__err("outofmem", "Out of memory");
-
- // Filtering for low-bit-depth images
- if (depth < 8) {
- filter_bytes = 1;
- width = img_width_bytes;
- }
-
- for (j=0; j < y; ++j) {
- // cur/prior filter buffers alternate
- stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes;
- stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes;
- stbi_uc *dest = a->out + stride*j;
- int nk = width * filter_bytes;
- int filter = *raw++;
-
- // check filter type
- if (filter > 4) {
- all_ok = stbi__err("invalid filter","Corrupt PNG");
- break;
- }
-
- // if first row, use special filter that doesn't sample previous row
- if (j == 0) filter = first_row_filter[filter];
-
- // perform actual filtering
- switch (filter) {
- case STBI__F_none:
- memcpy(cur, raw, nk);
- break;
- case STBI__F_sub:
- memcpy(cur, raw, filter_bytes);
- for (k = filter_bytes; k < nk; ++k)
- cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]);
- break;
- case STBI__F_up:
- for (k = 0; k < nk; ++k)
- cur[k] = STBI__BYTECAST(raw[k] + prior[k]);
- break;
- case STBI__F_avg:
- for (k = 0; k < filter_bytes; ++k)
- cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1));
- for (k = filter_bytes; k < nk; ++k)
- cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1));
- break;
- case STBI__F_paeth:
- for (k = 0; k < filter_bytes; ++k)
- cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0)
- for (k = filter_bytes; k < nk; ++k)
- cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes]));
- break;
- case STBI__F_avg_first:
- memcpy(cur, raw, filter_bytes);
- for (k = filter_bytes; k < nk; ++k)
- cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1));
- break;
- }
-
- raw += nk;
-
- // expand decoded bits in cur to dest, also adding an extra alpha channel if desired
- if (depth < 8) {
- stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
- stbi_uc *in = cur;
- stbi_uc *out = dest;
- stbi_uc inb = 0;
- stbi__uint32 nsmp = x*img_n;
-
- // expand bits to bytes first
- if (depth == 4) {
- for (i=0; i < nsmp; ++i) {
- if ((i & 1) == 0) inb = *in++;
- *out++ = scale * (inb >> 4);
- inb <<= 4;
+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;
+ stbi_uc* filter_buf;
+ int all_ok = 1;
+ 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");
+
+ // note: error exits here don't need to clean up a->out individually,
+ // stbi__do_png always does on error.
+ 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);
+ if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes))
+ return stbi__err("too large", "Corrupt PNG");
+ 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");
+
+ // Allocate two scan lines worth of filter workspace buffer.
+ filter_buf = (stbi_uc*)stbi__malloc_mad2(img_width_bytes, 2, 0);
+ if (!filter_buf)
+ return stbi__err("outofmem", "Out of memory");
+
+ // Filtering for low-bit-depth images
+ if (depth < 8) {
+ filter_bytes = 1;
+ width = img_width_bytes;
+ }
+
+ for (j = 0; j < y; ++j) {
+ // cur/prior filter buffers alternate
+ stbi_uc* cur = filter_buf + (j & 1) * img_width_bytes;
+ stbi_uc* prior = filter_buf + (~j & 1) * img_width_bytes;
+ stbi_uc* dest = a->out + stride * j;
+ int nk = width * filter_bytes;
+ int filter = *raw++;
+
+ // check filter type
+ if (filter > 4) {
+ all_ok = stbi__err("invalid filter", "Corrupt PNG");
+ break;
+ }
+
+ // if first row, use special filter that doesn't sample previous row
+ if (j == 0)
+ filter = first_row_filter[filter];
+
+ // perform actual filtering
+ switch (filter) {
+ case STBI__F_none:
+ memcpy(cur, raw, nk);
+ break;
+ case STBI__F_sub:
+ memcpy(cur, raw, filter_bytes);
+ for (k = filter_bytes; k < nk; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + cur[k - filter_bytes]);
+ break;
+ case STBI__F_up:
+ for (k = 0; k < nk; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + prior[k]);
+ break;
+ case STBI__F_avg:
+ for (k = 0; k < filter_bytes; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + (prior[k] >> 1));
+ for (k = filter_bytes; k < nk; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k - filter_bytes]) >> 1));
+ break;
+ case STBI__F_paeth:
+ for (k = 0; k < filter_bytes; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0)
+ for (k = filter_bytes; k < nk; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k - filter_bytes], prior[k], prior[k - filter_bytes]));
+ break;
+ case STBI__F_avg_first:
+ memcpy(cur, raw, filter_bytes);
+ for (k = filter_bytes; k < nk; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + (cur[k - filter_bytes] >> 1));
+ break;
+ }
+
+ raw += nk;
+
+ // expand decoded bits in cur to dest, also adding an extra alpha channel if desired
+ if (depth < 8) {
+ stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
+ stbi_uc* in = cur;
+ stbi_uc* out = dest;
+ stbi_uc inb = 0;
+ stbi__uint32 nsmp = x * img_n;
+
+ // expand bits to bytes first
+ if (depth == 4) {
+ for (i = 0; i < nsmp; ++i) {
+ if ((i & 1) == 0)
+ inb = *in++;
+ *out++ = scale * (inb >> 4);
+ inb <<= 4;
+ }
+ } else if (depth == 2) {
+ for (i = 0; i < nsmp; ++i) {
+ if ((i & 3) == 0)
+ inb = *in++;
+ *out++ = scale * (inb >> 6);
+ inb <<= 2;
+ }
+ } else {
+ STBI_ASSERT(depth == 1);
+ for (i = 0; i < nsmp; ++i) {
+ if ((i & 7) == 0)
+ inb = *in++;
+ *out++ = scale * (inb >> 7);
+ inb <<= 1;
+ }
}
- } else if (depth == 2) {
- for (i=0; i < nsmp; ++i) {
- if ((i & 3) == 0) inb = *in++;
- *out++ = scale * (inb >> 6);
- inb <<= 2;
+
+ // insert alpha=255 values if desired
+ if (img_n != out_n)
+ stbi__create_png_alpha_expand8(dest, dest, x, img_n);
+ } else if (depth == 8) {
+ if (img_n == out_n)
+ memcpy(dest, cur, x * img_n);
+ else
+ stbi__create_png_alpha_expand8(dest, cur, x, img_n);
+ } else if (depth == 16) {
+ // convert the image data from big-endian to platform-native
+ stbi__uint16* dest16 = (stbi__uint16*)dest;
+ stbi__uint32 nsmp = x * img_n;
+
+ if (img_n == out_n) {
+ for (i = 0; i < nsmp; ++i, ++dest16, cur += 2)
+ *dest16 = (cur[0] << 8) | cur[1];
+ } else {
+ STBI_ASSERT(img_n + 1 == out_n);
+ if (img_n == 1) {
+ for (i = 0; i < x; ++i, dest16 += 2, cur += 2) {
+ dest16[0] = (cur[0] << 8) | cur[1];
+ dest16[1] = 0xffff;
+ }
+ } else {
+ STBI_ASSERT(img_n == 3);
+ for (i = 0; i < x; ++i, dest16 += 4, cur += 6) {
+ dest16[0] = (cur[0] << 8) | cur[1];
+ dest16[1] = (cur[2] << 8) | cur[3];
+ dest16[2] = (cur[4] << 8) | cur[5];
+ dest16[3] = 0xffff;
+ }
+ }
}
- } else {
- STBI_ASSERT(depth == 1);
- for (i=0; i < nsmp; ++i) {
- if ((i & 7) == 0) inb = *in++;
- *out++ = scale * (inb >> 7);
- inb <<= 1;
+ }
+ }
+
+ STBI_FREE(filter_buf);
+ if (!all_ok)
+ return 0;
+
+ 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);
+ if (!final)
+ return stbi__err("outofmem", "Out of memory");
+ 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;
}
- }
-
- // insert alpha=255 values if desired
- if (img_n != out_n)
- stbi__create_png_alpha_expand8(dest, dest, x, img_n);
- } else if (depth == 8) {
- if (img_n == out_n)
- memcpy(dest, cur, x*img_n);
- else
- stbi__create_png_alpha_expand8(dest, cur, x, img_n);
- } else if (depth == 16) {
- // convert the image data from big-endian to platform-native
- stbi__uint16 *dest16 = (stbi__uint16*)dest;
- stbi__uint32 nsmp = x*img_n;
-
- if (img_n == out_n) {
- for (i = 0; i < nsmp; ++i, ++dest16, cur += 2)
- *dest16 = (cur[0] << 8) | cur[1];
- } else {
- STBI_ASSERT(img_n+1 == out_n);
- if (img_n == 1) {
- for (i = 0; i < x; ++i, dest16 += 2, cur += 2) {
- dest16[0] = (cur[0] << 8) | cur[1];
- dest16[1] = 0xffff;
- }
- } else {
- STBI_ASSERT(img_n == 3);
- for (i = 0; i < x; ++i, dest16 += 4, cur += 6) {
- dest16[0] = (cur[0] << 8) | cur[1];
- dest16[1] = (cur[2] << 8) | cur[3];
- dest16[2] = (cur[4] << 8) | cur[5];
- dest16[3] = 0xffff;
- }
+ 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;
- STBI_FREE(filter_buf);
- if (!all_ok) return 0;
+ 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;
- return 1;
+ // 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__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);
- if (!final) return stbi__err("outofmem", "Out of memory");
- 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;
+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);
- return 1;
+ 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__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__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_global = 0;
-static int stbi__de_iphone_flag_global = 0;
+static int stbi__de_iphone_flag_global = 0;
-STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply)
-{
- stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply;
+STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) {
+ stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply;
}
-STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
-{
- stbi__de_iphone_flag_global = flag_true_if_should_convert;
+STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) {
+ stbi__de_iphone_flag_global = flag_true_if_should_convert;
}
#ifndef STBI_THREAD_LOCAL
-#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global
-#define stbi__de_iphone_flag stbi__de_iphone_flag_global
+#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global
+#define stbi__de_iphone_flag stbi__de_iphone_flag_global
#else
static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set;
static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set;
-STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)
-{
- stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply;
- stbi__unpremultiply_on_load_set = 1;
+STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) {
+ stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply;
+ stbi__unpremultiply_on_load_set = 1;
}
-STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert)
-{
- stbi__de_iphone_flag_local = flag_true_if_should_convert;
- stbi__de_iphone_flag_set = 1;
+STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) {
+ stbi__de_iphone_flag_local = flag_true_if_should_convert;
+ stbi__de_iphone_flag_set = 1;
}
-#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \
- ? stbi__unpremultiply_on_load_local \
- : stbi__unpremultiply_on_load_global)
-#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \
- ? stbi__de_iphone_flag_local \
- : stbi__de_iphone_flag_global)
+#define stbi__unpremultiply_on_load \
+ (stbi__unpremultiply_on_load_set ? stbi__unpremultiply_on_load_local : stbi__unpremultiply_on_load_global)
+#define stbi__de_iphone_flag (stbi__de_iphone_flag_set ? stbi__de_iphone_flag_local : stbi__de_iphone_flag_global)
#endif // STBI_THREAD_LOCAL
-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];
+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];
- 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[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;
}
- 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;
- }
- }
- }
+ } 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))
+#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]={0};
- 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;
+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] = {0};
+ 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;
+ z->expanded = NULL;
+ z->idata = NULL;
+ z->out = NULL;
- if (!stbi__check_png_header(s)) return 0;
+ if (!stbi__check_png_header(s))
+ return 0;
- if (scan == STBI__SCAN_type) return 1;
+ 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'):
+ 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");
+ 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");
+ if (c.length != 13)
+ return stbi__err("bad IHDR len", "Corrupt PNG");
s->img_x = stbi__get32be(s);
s->img_y = stbi__get32be(s);
- if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
- if (s->img_x > STBI_MAX_DIMENSIONS) 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 (s->img_y > STBI_MAX_DIMENSIONS)
+ return stbi__err("too large", "Very large image (corrupt?)");
+ if (s->img_x > STBI_MAX_DIMENSIONS)
+ 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");
+ 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");
} 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 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");
}
// even with 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");
+ 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;
+ 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");
+ 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);
+ 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;
- // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now.
- if (scan == STBI__SCAN_header) { ++s->img_n; return 1; }
- if (z->depth == 16) {
- for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning
- tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
- } else {
- for (k = 0; k < s->img_n && k < 3; ++k)
- tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
- }
+ 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;
+ // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now.
+ if (scan == STBI__SCAN_header) {
+ ++s->img_n;
+ return 1;
+ }
+ if (z->depth == 16) {
+ for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning
+ tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
+ } else {
+ for (k = 0; k < s->img_n && k < 3; ++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");
+ 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) {
- // header scan definitely stops at first IDAT
- if (pal_img_n)
- s->img_n = pal_img_n;
- return 1;
+ // header scan definitely stops at first IDAT
+ if (pal_img_n)
+ s->img_n = pal_img_n;
+ return 1;
}
- if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes");
- if ((int)(ioff + c.length) < (int)ioff) return 0;
+ if (c.length > (1u << 30))
+ return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes");
+ 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;
+ 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");
+ 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'): {
+ 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");
+ 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;
+ 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;
+ 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 (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);
+ 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;
+ // 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;
+ // non-paletted image with tRNS -> source image has (constant) alpha
+ ++s->img_n;
}
- STBI_FREE(z->expanded); z->expanded = NULL;
+ STBI_FREE(z->expanded);
+ z->expanded = NULL;
// end of PNG chunk, read and skip CRC
stbi__get32be(s);
return 1;
- }
+ }
- default:
+ default:
// if critical, fail
- if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+ 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");
+#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);
- }
+ }
+ // 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 if (p->depth == 16)
- ri->bits_per_channel = 16;
- else
- return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color 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 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 if (p->depth == 16)
+ ri->bits_per_channel = 16;
+ else
+ return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color 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;
-static int stbi__png_test(stbi__context *s)
-{
- int r;
- r = stbi__check_png_header(s);
- stbi__rewind(s);
- return r;
+ return result;
}
-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 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_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_test(stbi__context* s) {
+ int r;
+ r = stbi__check_png_header(s);
+ stbi__rewind(s);
+ return r;
}
-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__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;/* >>= 1;*/ }
- return n;
+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; /* >>= 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__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(unsigned 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 < 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;
- int extra_read;
+static int stbi__shiftsigned(unsigned 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 < 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;
+ int extra_read;
} stbi__bmp_data;
-static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress)
-{
- // BI_BITFIELDS specifies masks explicitly, don't override
- if (compress == 3)
- return 1;
-
- if (compress == 0) {
- if (info->bpp == 16) {
- info->mr = 31u << 10;
- info->mg = 31u << 5;
- info->mb = 31u << 0;
- } else 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 {
- // otherwise, use defaults, which is all-0
- info->mr = info->mg = info->mb = info->ma = 0;
- }
- return 1;
- }
- return 0; // error
-}
-
-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;
- info->extra_read = 14;
-
- if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP");
-
- 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");
- if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes
- if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel
- 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) {
- stbi__bmp_set_mask_defaults(info, compress);
- } else if (compress == 3) {
- info->mr = stbi__get32le(s);
- info->mg = stbi__get32le(s);
- info->mb = stbi__get32le(s);
- info->extra_read += 12;
- // 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 {
- // V4/V5 header
- 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);
- if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs
- stbi__bmp_set_mask_defaults(info, compress);
- 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);
-
- if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
- if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
-
- 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 - info.extra_read - 24) / 3;
- } else {
- if (info.bpp < 16)
- psize = (info.offset - info.extra_read - info.hsz) >> 2;
- }
- if (psize == 0) {
- // accept some number of extra bytes after the header, but if the offset points either to before
- // the header ends or implies a large amount of extra data, reject the file as malformed
- int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original);
- int header_limit = 1024; // max we actually read is below 256 bytes currently.
- int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size.
- if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) {
- return stbi__errpuc("bad header", "Corrupt BMP");
- }
- // we established that bytes_read_so_far is positive and sensible.
- // the first half of this test rejects offsets that are either too small positives, or
- // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn
- // ensures the number computed in the second half of the test can't overflow.
- if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) {
- return stbi__errpuc("bad offset", "Corrupt BMP");
- } else {
- stbi__skip(s, info.offset - bytes_read_so_far);
- }
- }
-
- if (info.bpp == 24 && ma == 0xff000000)
- s->img_n = 3;
- else
- 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 - info.extra_read - 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 (target == 4) out[z++] = 255;
- if (i+1 == (int) s->img_x) break;
- if((--bit_offset) < 0) {
- bit_offset = 7;
- v = stbi__get8(s);
- }
+static int stbi__bmp_set_mask_defaults(stbi__bmp_data* info, int compress) {
+ // BI_BITFIELDS specifies masks explicitly, don't override
+ if (compress == 3)
+ return 1;
+
+ if (compress == 0) {
+ if (info->bpp == 16) {
+ info->mr = 31u << 10;
+ info->mg = 31u << 5;
+ info->mb = 31u << 0;
+ } else 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 {
+ // otherwise, use defaults, which is all-0
+ info->mr = info->mg = info->mb = info->ma = 0;
+ }
+ return 1;
+ }
+ return 0; // error
+}
+
+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;
+ info->extra_read = 14;
+
+ if (info->offset < 0)
+ return stbi__errpuc("bad BMP", "bad BMP");
+
+ 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");
+ if (compress >= 4)
+ return stbi__errpuc("BMP JPEG/PNG",
+ "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes
+ if (compress == 3 && info->bpp != 16 && info->bpp != 32)
+ return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel
+ 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);
}
- 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;
+ if (info->bpp == 16 || info->bpp == 32) {
+ if (compress == 0) {
+ stbi__bmp_set_mask_defaults(info, compress);
+ } else if (compress == 3) {
+ info->mr = stbi__get32le(s);
+ info->mg = stbi__get32le(s);
+ info->mb = stbi__get32le(s);
+ info->extra_read += 12;
+ // 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");
}
- 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 - info.extra_read - 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);
- if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }
- }
- 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 {
+ // V4/V5 header
+ 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);
+ if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs
+ stbi__bmp_set_mask_defaults(info, compress);
+ 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);
+
+ if (s->img_y > STBI_MAX_DIMENSIONS)
+ return stbi__errpuc("too large", "Very large image (corrupt?)");
+ if (s->img_x > STBI_MAX_DIMENSIONS)
+ return stbi__errpuc("too large", "Very large image (corrupt?)");
+
+ 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 - info.extra_read - 24) / 3;
+ } else {
+ if (info.bpp < 16)
+ psize = (info.offset - info.extra_read - info.hsz) >> 2;
+ }
+ if (psize == 0) {
+ // accept some number of extra bytes after the header, but if the offset points either to before
+ // the header ends or implies a large amount of extra data, reject the file as malformed
+ int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original);
+ int header_limit = 1024; // max we actually read is below 256 bytes currently.
+ int extra_data_limit = 256 * 4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size.
+ if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) {
+ return stbi__errpuc("bad header", "Corrupt BMP");
+ }
+ // we established that bytes_read_so_far is positive and sensible.
+ // the first half of this test rejects offsets that are either too small positives, or
+ // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn
+ // ensures the number computed in the second half of the test can't overflow.
+ if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) {
+ return stbi__errpuc("bad offset", "Corrupt BMP");
+ } else {
+ stbi__skip(s, info.offset - bytes_read_so_far);
+ }
+ }
+
+ if (info.bpp == 24 && ma == 0xff000000)
+ s->img_n = 3;
+ else
+ 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 - info.extra_read - 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 (target == 4)
+ out[z++] = 255;
+ if (i + 1 == (int)s->img_x)
+ break;
+ 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 - info.extra_read - 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);
+ if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) {
+ STBI_FREE(out);
+ return stbi__errpuc("bad masks", "Corrupt BMP");
+ }
+ }
+ 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);
+ }
}
- } 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;
}
- }
- 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;
+ }
+ }
+
+ 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)
-{
+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
+ stbi__get8(s); // discard Offset
tga_colormap_type = stbi__get8(s); // colormap type
- if( tga_colormap_type > 1 ) {
+ if (tga_colormap_type > 1) {
stbi__rewind(s);
- return 0; // only RGB or indexed allowed
+ 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_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__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
+ 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) ) {
+ 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
+ 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 ) {
+ if (tga_w < 1) {
stbi__rewind(s);
- return 0; // test width
+ return 0; // test width
}
tga_h = stbi__get16le(s);
- if( tga_h < 1 ) {
+ if (tga_h < 1) {
stbi__rewind(s);
- return 0; // test height
+ return 0; // test height
}
tga_bits_per_pixel = stbi__get8(s); // bits per pixel
- stbi__get8(s); // ignore alpha bits
+ stbi__get8(s); // ignore alpha bits
if (tga_colormap_bpp != 0) {
- if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
+ 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);
} 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 (!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 (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
+ 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);
- STBI_NOTUSED(tga_x_origin); // @TODO
- STBI_NOTUSED(tga_y_origin); // @TODO
-
- if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
- if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
-
- // 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)
- {
- if (tga_palette_len == 0) { /* you have to have at least one entry! */
- STBI_FREE(tga_data);
- return stbi__errpuc("bad palette", "Corrupt TGA");
- }
-
- // 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;
+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);
+ STBI_NOTUSED(tga_x_origin); // @TODO
+ STBI_NOTUSED(tga_y_origin); // @TODO
+
+ if (tga_height > STBI_MAX_DIMENSIONS)
+ return stbi__errpuc("too large", "Very large image (corrupt?)");
+ if (tga_width > STBI_MAX_DIMENSIONS)
+ return stbi__errpuc("too large", "Very large image (corrupt?)");
+
+ // 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) {
+ if (tga_palette_len == 0) { /* you have to have at least one entry! */
+ STBI_FREE(tga_data);
+ return stbi__errpuc("bad palette", "Corrupt TGA");
}
- } 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;
+
+ // 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");
}
- } 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);
+ 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 in the data raw
- for (j = 0; j < tga_comp; ++j) {
- raw_data[j] = stbi__get8(s);
- }
+ read_next_pixel = 1;
}
- // 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;
+ // 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;
- STBI_NOTUSED(tga_palette_start);
- // OK, done
- return tga_data;
-}
-#endif
-
-// *************************************************************************************************
-// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB
+ }
+ // clear my palette, if I had one
+ if (tga_palette != NULL) {
+ STBI_FREE(tga_palette);
+ }
+ }
-#ifndef STBI_NO_PSD
-static int stbi__psd_test(stbi__context *s)
-{
- int r = (stbi__get32be(s) == 0x38425053);
- stbi__rewind(s);
- return r;
-}
+ // 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;
+ }
+ }
-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--;
- }
- }
- }
+ // 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);
- return 1;
+ // 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;
+ STBI_NOTUSED(tga_palette_start);
+ // OK, done
+ return tga_data;
}
+#endif
+
+// *************************************************************************************************
+// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB
-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);
-
- if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
- if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
-
- // 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 preceded 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");
+#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 {
- // 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 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);
+
+ if (h > STBI_MAX_DIMENSIONS)
+ return stbi__errpuc("too large", "Very large image (corrupt?)");
+ if (w > STBI_MAX_DIMENSIONS)
+ return stbi__errpuc("too large", "Very large image (corrupt?)");
+
+ // 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 preceded 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 {
- stbi_uc *p = out+channel;
- stbi_uc val = channel == 3 ? 255 : 0;
- for (i = 0; i < pixelCount; i++, p += 4)
- *p = val;
+ // Read the RLE data.
+ if (!stbi__psd_decode_rle(s, p, pixelCount)) {
+ STBI_FREE(out);
+ return stbi__errpuc("corrupt", "bad RLE data");
+ }
}
- } 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 {
+ // 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 {
- 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);
- }
+ 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);
+ }
+ }
+
+ // 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);
+ } 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
- }
+ // 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;
+ if (comp)
+ *comp = 4;
+ *y = h;
+ *x = w;
- return out;
+ 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];
+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
+ // this will (should...) cater for even some bizarre stuff like having data
// for the same channel in multiple packets.
- do {
- stbi__pic_packet *packet;
+ do {
+ stbi__pic_packet* packet;
- if (num_packets==sizeof(packets)/sizeof(packets[0]))
- return stbi__errpuc("bad format","too many packets");
+ if (num_packets == sizeof(packets) / sizeof(packets[0]))
+ return stbi__errpuc("bad format", "too many packets");
- packet = &packets[num_packets++];
+ packet = &packets[num_packets++];
- chained = stbi__get8(s);
- packet->size = stbi__get8(s);
- packet->type = stbi__get8(s);
- packet->channel = stbi__get8(s);
+ chained = stbi__get8(s);
+ packet->size = stbi__get8(s);
+ packet->type = stbi__get8(s);
+ packet->channel = stbi__get8(s);
- act_comp |= packet->channel;
+ act_comp |= packet->channel;
- 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);
+ 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);
- *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel?
+ *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel?
- for(y=0; y<height; ++y) {
- int packet_idx;
+ for (y = 0; y < height; ++y) {
+ int packet_idx;
- 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 (packet_idx = 0; packet_idx < num_packets; ++packet_idx) {
+ stbi__pic_packet* packet = &packets[packet_idx];
+ stbi_uc* dest = result + y * width * 4;
- switch (packet->type) {
+ switch (packet->type) {
default:
- return stbi__errpuc("bad format","packet has bad compression type");
+ return stbi__errpuc("bad format", "packet has bad compression type");
- case 0: {//uncompressed
- int x;
+ case 0: { // uncompressed
+ int x;
- for(x=0;x<width;++x, dest+=4)
- if (!stbi__readval(s,packet->channel,dest))
- return 0;
- break;
+ 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;
-
- while (left>0) {
- stbi_uc count,value[4];
-
- count=stbi__get8(s);
- if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)");
+ case 1: // Pure RLE
+ {
+ int left = width, i;
- if (count > left)
- count = (stbi_uc) left;
+ while (left > 0) {
+ stbi_uc count, value[4];
- if (!stbi__readval(s,packet->channel,value)) return 0;
+ count = stbi__get8(s);
+ if (stbi__at_eof(s))
+ return stbi__errpuc("bad file", "file too short (pure read count)");
- for(i=0; i<count; ++i,dest+=4)
- stbi__copyval(packet->channel,dest,value);
- left -= count;
- }
- }
- break;
+ if (count > left)
+ count = (stbi_uc)left;
- 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 (!stbi__readval(s, packet->channel, value))
+ return 0;
- if (count >= 128) { // Repeated
- stbi_uc value[4];
+ for (i = 0; i < count; ++i, dest += 4)
+ stbi__copyval(packet->channel, dest, value);
+ left -= count;
+ }
+ } break;
- if (count==128)
- count = stbi__get16be(s);
- else
- count -= 127;
- if (count > left)
- return stbi__errpuc("bad file","scanline overrun");
+ 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 (!stbi__readval(s,packet->channel,value))
- return 0;
+ if (count >= 128) { // Repeated
+ stbi_uc value[4];
- 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;
+ 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;
+
+ 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;
+ 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);
+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;
+ if (!comp)
+ comp = &internal_comp;
- for (i=0; i<92; ++i)
- stbi__get8(s);
+ for (i = 0; i < 92; ++i)
+ stbi__get8(s);
- x = stbi__get16be(s);
- y = stbi__get16be(s);
+ x = stbi__get16be(s);
+ y = stbi__get16be(s);
- if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
- if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
+ if (y > STBI_MAX_DIMENSIONS)
+ return stbi__errpuc("too large", "Very large image (corrupt?)");
+ if (x > STBI_MAX_DIMENSIONS)
+ return stbi__errpuc("too large", "Very large image (corrupt?)");
- 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");
+ 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'
+ 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);
- if (!result) return stbi__errpuc("outofmem", "Out of memory");
- memset(result, 0xff, x*y*4);
+ // intermediate buffer is RGBA
+ result = (stbi_uc*)stbi__malloc_mad3(x, y, 4, 0);
+ if (!result)
+ return stbi__errpuc("outofmem", "Out of memory");
+ 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);
+ 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;
+ return result;
}
-static int stbi__pic_test(stbi__context *s)
-{
- int r = stbi__pic_test_core(s);
- stbi__rewind(s);
- return r;
+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 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 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");
-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");
- 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;
- 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 (g->w > STBI_MAX_DIMENSIONS)
+ return stbi__err("too large", "Very large image (corrupt?)");
+ if (g->h > STBI_MAX_DIMENSIONS)
+ return stbi__err("too large", "Very large image (corrupt?)");
- if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
- if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
+ if (comp != 0)
+ *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments
- 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 (is_info) return 1;
+ if (g->flags & 0x80)
+ stbi__gif_parse_colortable(s, g->pal, 2 << (g->flags & 7), -1);
- if (g->flags & 0x80)
- stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1);
+ return 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 (!g)
+ return stbi__err("outofmem", "Out of memory");
+ 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 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 (!g) return stbi__err("outofmem", "Out of memory");
- 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");
- }
+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 (oldcode >= 0) {
- p = &g->codes[avail++];
- if (avail > 8192) {
- return stbi__errpuc("too many codes", "Corrupt GIF");
- }
+ if (g->cur_y >= g->max_y)
+ return;
+
+ idx = g->cur_x + g->cur_y;
+ p = &g->out[idx];
+ g->history[idx / 4] = 1;
- 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");
+ 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;
- stbi__out_gif_code(g, (stbi__uint16) code);
+ if (g->cur_x >= g->max_x) {
+ g->cur_x = g->start_x;
+ g->cur_y += g->step;
- if ((avail & codemask) == 0 && avail <= 0x0FFF) {
- codesize++;
- codemask = (1 << codesize) - 1;
- }
+ 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;
+ }
- oldcode = code;
- } else {
- return stbi__errpuc("illegal code in raster", "Corrupt GIF");
- }
- }
- }
+ // 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;
- STBI_NOTUSED(req_comp);
-
- // 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
- if (!stbi__mad3sizes_valid(4, g->w, g->h, 0))
- return stbi__errpuc("too large", "GIF image is too large");
- pcount = g->w * g->h;
- g->out = (stbi_uc *) stbi__malloc(4 * pcount);
- g->background = (stbi_uc *) stbi__malloc(4 * pcount);
- g->history = (stbi_uc *) stbi__malloc(pcount);
- if (!g->out || !g->background || !g->history)
- return stbi__errpuc("outofmem", "Out of memory");
-
- // image is treated as "transparent" 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 the color that was there the previous frame.
- memset(g->out, 0x00, 4 * pcount);
- memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent)
- memset(g->history, 0x00, pcount); // pixels that were affected previous frame
- first_frame = 1;
- } else {
- // second frame - how do we dispose 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 );
+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;
+ STBI_NOTUSED(req_comp);
+
+ // 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
+ if (!stbi__mad3sizes_valid(4, g->w, g->h, 0))
+ return stbi__errpuc("too large", "GIF image is too large");
+ pcount = g->w * g->h;
+ g->out = (stbi_uc*)stbi__malloc(4 * pcount);
+ g->background = (stbi_uc*)stbi__malloc(4 * pcount);
+ g->history = (stbi_uc*)stbi__malloc(pcount);
+ if (!g->out || !g->background || !g->history)
+ return stbi__errpuc("outofmem", "Out of memory");
+
+ // image is treated as "transparent" 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 the color that was there the previous frame.
+ memset(g->out, 0x00, 4 * pcount);
+ memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent)
+ memset(g->history, 0x00, pcount); // pixels that were affected previous frame
+ first_frame = 1;
+ } else {
+ // second frame - how do we dispose 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 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 */
- {
+ } 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;
+ 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");
+ 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->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;
// if the width of the specified rectangle is 0, that means
// we may not see *any* pixels or the image is malformed;
// to make sure this is caught, move the current y down to
// max_y (which is what out_gif_code checks).
if (w == 0)
- g->cur_y = g->max_y;
+ g->cur_y = g->max_y;
g->lflags = stbi__get8(s);
if (g->lflags & 0x40) {
- g->step = 8 * g->line_size; // first interlaced spacing
- g->parse = 3;
+ g->step = 8 * g->line_size; // first interlaced spacing
+ g->parse = 3;
} else {
- g->step = g->line_size;
- g->parse = 0;
+ 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;
+ 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;
+ g->color_table = (stbi_uc*)g->pal;
} else
- return stbi__errpuc("missing color table", "Corrupt GIF");
+ return stbi__errpuc("missing color table", "Corrupt GIF");
o = stbi__process_gif_raster(s, g);
- if (!o) return NULL;
+ if (!o)
+ 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 );
- }
- }
+ // 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.
- {
+ 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;
- }
+ 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);
+ stbi__skip(s, len);
}
break;
- }
+ }
- case 0x3B: // gif stream termination code
- return (stbi_uc *) s; // using '1' causes warning on some compilers
+ case 0x3B: // gif stream termination code
+ return (stbi_uc*)s; // using '1' causes warning on some compilers
- default:
+ default:
return stbi__errpuc("unknown code", "Corrupt GIF");
- }
- }
+ }
+ }
}
-static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays)
-{
- STBI_FREE(g->out);
- STBI_FREE(g->history);
- STBI_FREE(g->background);
+static void* stbi__load_gif_main_outofmem(stbi__gif* g, stbi_uc* out, int** delays) {
+ STBI_FREE(g->out);
+ STBI_FREE(g->history);
+ STBI_FREE(g->background);
- if (out) STBI_FREE(out);
- if (delays && *delays) STBI_FREE(*delays);
- return stbi__errpuc("outofmem", "Out of memory");
+ if (out)
+ STBI_FREE(out);
+ if (delays && *delays)
+ STBI_FREE(*delays);
+ return stbi__errpuc("outofmem", "Out of memory");
}
-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;
- int out_size = 0;
- int delays_size = 0;
-
- STBI_NOTUSED(out_size);
- STBI_NOTUSED(delays_size);
-
- 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) {
- void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );
- if (!tmp)
- return stbi__load_gif_main_outofmem(&g, out, delays);
- else {
- out = (stbi_uc*) tmp;
- out_size = layers * stride;
- }
-
- if (delays) {
- int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers );
- if (!new_delays)
- return stbi__load_gif_main_outofmem(&g, out, delays);
- *delays = new_delays;
- delays_size = layers * sizeof(int);
- }
- } else {
- out = (stbi_uc*)stbi__malloc( layers * stride );
- if (!out)
- return stbi__load_gif_main_outofmem(&g, out, delays);
- out_size = layers * stride;
- if (delays) {
- *delays = (int*) stbi__malloc( layers * sizeof(int) );
- if (!*delays)
- return stbi__load_gif_main_outofmem(&g, out, delays);
- delays_size = layers * sizeof(int);
- }
- }
- memcpy( out + ((layers - 1) * stride), u, stride );
- if (layers >= 2) {
- two_back = out - 2 * stride;
- }
+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;
+ int out_size = 0;
+ int delays_size = 0;
+
+ STBI_NOTUSED(out_size);
+ STBI_NOTUSED(delays_size);
- if (delays) {
- (*delays)[layers - 1U] = g.delay;
+ 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) {
+ void* tmp = (stbi_uc*)STBI_REALLOC_SIZED(out, out_size, layers * stride);
+ if (!tmp)
+ return stbi__load_gif_main_outofmem(&g, out, delays);
+ else {
+ out = (stbi_uc*)tmp;
+ out_size = layers * stride;
+ }
+
+ if (delays) {
+ int* new_delays = (int*)STBI_REALLOC_SIZED(*delays, delays_size, sizeof(int) * layers);
+ if (!new_delays)
+ return stbi__load_gif_main_outofmem(&g, out, delays);
+ *delays = new_delays;
+ delays_size = layers * sizeof(int);
+ }
+ } else {
+ out = (stbi_uc*)stbi__malloc(layers * stride);
+ if (!out)
+ return stbi__load_gif_main_outofmem(&g, out, delays);
+ out_size = layers * stride;
+ if (delays) {
+ *delays = (int*)stbi__malloc(layers * sizeof(int));
+ if (!*delays)
+ return stbi__load_gif_main_outofmem(&g, out, delays);
+ delays_size = 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);
+ } while (u != 0);
- // free temp buffer;
- STBI_FREE(g.out);
- STBI_FREE(g.history);
- STBI_FREE(g.background);
+ // 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);
+ // 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.");
- }
+ *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));
- STBI_NOTUSED(ri);
-
- 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);
- } else if (g.out) {
- // if there was an error and we allocated an image buffer, free it!
- STBI_FREE(g.out);
- }
-
- // 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 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));
+ STBI_NOTUSED(ri);
+
+ 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);
+ } else if (g.out) {
+ // if there was an error and we allocated an image buffer, free it!
+ STBI_FREE(g.out);
+ }
+
+ // 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_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;
+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';
+#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);
+ 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);
- }
+ 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;
+ 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 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);
-
- if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
- if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
-
- *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");
+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);
+
+ if (height > STBI_MAX_DIMENSIONS)
+ return stbi__errpf("too large", "Very large image (corrupt?)");
+ if (width > STBI_MAX_DIMENSIONS)
+ return stbi__errpf("too large", "Very large image (corrupt?)");
+
+ *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 == 0) || (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 == 0) || (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 (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 == 0) || (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 == 0) || (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);
- }
+ 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;
+ 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_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);
- if (p == NULL) {
- stbi__rewind( s );
- return 0;
- }
- if (x) *x = s->img_x;
- if (y) *y = s->img_y;
- if (comp) {
- if (info.bpp == 24 && info.ma == 0xff000000)
- *comp = 3;
- else
- *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);
+ if (p == NULL) {
+ stbi__rewind(s);
+ return 0;
+ }
+ if (x)
+ *x = s->img_x;
+ if (y)
+ *y = s->img_y;
+ if (comp) {
+ if (info.bpp == 24 && info.ma == 0xff000000)
+ *comp = 3;
+ else
+ *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;
- }
- STBI_NOTUSED(stbi__get32be(s));
- STBI_NOTUSED(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;
+ }
+ STBI_NOTUSED(stbi__get32be(s));
+ STBI_NOTUSED(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;
- }
+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);
+ 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;
- }
+ *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);
+ stbi__skip(s, 8);
- do {
- stbi__pic_packet *packet;
+ do {
+ stbi__pic_packet* packet;
- if (num_packets==sizeof(packets)/sizeof(packets[0]))
- return 0;
+ 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;
+ 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);
+ 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);
+ *comp = (act_comp & 0x10 ? 4 : 3);
- return 1;
+ 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);
-
- ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n);
- if (ri->bits_per_channel == 0)
- return 0;
-
- if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
- if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
-
- *x = s->img_x;
- *y = s->img_y;
- if (comp) *comp = s->img_n;
-
- if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0))
- return stbi__errpuc("too large", "PNM too large");
-
- out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0);
- if (!out) return stbi__errpuc("outofmem", "Out of memory");
- if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) {
- STBI_FREE(out);
- return stbi__errpuc("bad PNM", "PNM file truncated");
- }
-
- if (req_comp && req_comp != s->img_n) {
- if (ri->bits_per_channel == 16) {
- out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y);
- } else {
- 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 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_skip_whitespace(stbi__context *s, char *c)
-{
- for (;;) {
- while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
- *c = (char) stbi__get8(s);
+ ri->bits_per_channel = stbi__pnm_info(s, (int*)&s->img_x, (int*)&s->img_y, (int*)&s->img_n);
+ if (ri->bits_per_channel == 0)
+ return 0;
+
+ if (s->img_y > STBI_MAX_DIMENSIONS)
+ return stbi__errpuc("too large", "Very large image (corrupt?)");
+ if (s->img_x > STBI_MAX_DIMENSIONS)
+ return stbi__errpuc("too large", "Very large image (corrupt?)");
+
+ *x = s->img_x;
+ *y = s->img_y;
+ if (comp)
+ *comp = s->img_n;
+
+ if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0))
+ return stbi__errpuc("too large", "PNM too large");
- if (stbi__at_eof(s) || *c != '#')
- break;
+ out = (stbi_uc*)stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0);
+ if (!out)
+ return stbi__errpuc("outofmem", "Out of memory");
+ if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) {
+ STBI_FREE(out);
+ return stbi__errpuc("bad PNM", "PNM file truncated");
+ }
- while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' )
- *c = (char) stbi__get8(s);
- }
+ if (req_comp && req_comp != s->img_n) {
+ if (ri->bits_per_channel == 16) {
+ out = (stbi_uc*)stbi__convert_format16((stbi__uint16*)out, s->img_n, req_comp, s->img_x, s->img_y);
+ } else {
+ 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_isdigit(char c)
-{
- return c >= '0' && c <= '9';
+static int stbi__pnm_isspace(char c) {
+ return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
}
-static int stbi__pnm_getinteger(stbi__context *s, char *c)
-{
- int value = 0;
+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);
- while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
- value = value*10 + (*c - '0');
- *c = (char) stbi__get8(s);
- if((value > 214748364) || (value == 214748364 && *c > '7'))
- return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int");
- }
+ if (stbi__at_eof(s) || *c != '#')
+ break;
- return value;
+ while (!stbi__at_eof(s) && *c != '\n' && *c != '\r')
+ *c = (char)stbi__get8(s);
+ }
}
-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_isdigit(char c) { return c >= '0' && c <= '9'; }
+
+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);
+ if ((value > 214748364) || (value == 214748364 && *c > '7'))
+ return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int");
+ }
+
+ return value;
+}
+
+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
- if(*x == 0)
- return stbi__err("invalid width", "PPM image header had zero or overflowing width");
- stbi__pnm_skip_whitespace(s, &c);
+ *x = stbi__pnm_getinteger(s, &c); // read width
+ if (*x == 0)
+ return stbi__err("invalid width", "PPM image header had zero or overflowing width");
+ stbi__pnm_skip_whitespace(s, &c);
- *y = stbi__pnm_getinteger(s, &c); // read height
- if (*y == 0)
- return stbi__err("invalid width", "PPM image header had zero or overflowing width");
- stbi__pnm_skip_whitespace(s, &c);
+ *y = stbi__pnm_getinteger(s, &c); // read height
+ if (*y == 0)
+ return stbi__err("invalid width", "PPM image header had zero or overflowing width");
+ stbi__pnm_skip_whitespace(s, &c);
- maxv = stbi__pnm_getinteger(s, &c); // read max value
- if (maxv > 65535)
- return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images");
- else if (maxv > 255)
- return 16;
- else
- return 8;
+ maxv = stbi__pnm_getinteger(s, &c); // read max value
+ if (maxv > 65535)
+ return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images");
+ else if (maxv > 255)
+ return 16;
+ else
+ return 8;
}
-static int stbi__pnm_is16(stbi__context *s)
-{
- if (stbi__pnm_info(s, NULL, NULL, NULL) == 16)
- return 1;
- return 0;
+static int stbi__pnm_is16(stbi__context* s) {
+ if (stbi__pnm_info(s, NULL, NULL, NULL) == 16)
+ return 1;
+ return 0;
}
#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
- #ifndef STBI_NO_PNM
- if (stbi__pnm_is16(s)) return 1;
- #endif
- return 0;
+#ifndef STBI_NO_PNM
+ if (stbi__pnm_is16(s))
+ return 1;
+#endif
+ 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");
+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_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");
+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_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
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)
+ 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
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);
// 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
STBIWDEF int stbi_write_tga_with_rle;
STBIWDEF int stbi_write_png_compression_level;
STBIWDEF 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_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_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);
#ifdef STBIW_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);
+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_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_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 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_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_write_tga_with_rle = 1;
-int stbi_write_force_png_filter = -1;
+int stbi_write_tga_with_rle = 1;
+int stbi_write_force_png_filter = -1;
#endif
static int stbi__flip_vertically_on_write = 0;
-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;
- unsigned char buffer[64];
- int buf_used;
+typedef struct {
+ stbi_write_func* func;
+ void* context;
+ unsigned char buffer[64];
+ int buf_used;
} 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(_WIN32) && defined(STBIW_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(_WIN32) && defined(STBIW_WINDOWS_UTF8)
- wchar_t wMode[64];
- wchar_t wFilename[1024];
- if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
- return 0;
+ wchar_t wMode[64];
+ wchar_t wFilename[1024];
+ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename) / sizeof(*wFilename)))
+ return 0;
- if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
- return 0;
+ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode) / sizeof(*wMode)))
+ return 0;
#if defined(_MSC_VER) && _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__write_flush(stbi__write_context *s)
-{
- if (s->buf_used) {
- s->func(s->context, &s->buffer, s->buf_used);
- s->buf_used = 0;
- }
+static void stbiw__write_flush(stbi__write_context* s) {
+ if (s->buf_used) {
+ s->func(s->context, &s->buffer, s->buf_used);
+ s->buf_used = 0;
+ }
}
-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__write1(stbi__write_context *s, unsigned char a)
-{
- if ((size_t)s->buf_used + 1 > sizeof(s->buffer))
- stbiw__write_flush(s);
- s->buffer[s->buf_used++] = a;
+static void stbiw__write1(stbi__write_context* s, unsigned char a) {
+ if ((size_t)s->buf_used + 1 > sizeof(s->buffer))
+ stbiw__write_flush(s);
+ s->buffer[s->buf_used++] = a;
}
-static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
-{
- int n;
- if ((size_t)s->buf_used + 3 > sizeof(s->buffer))
- stbiw__write_flush(s);
- n = s->buf_used;
- s->buf_used = n+3;
- s->buffer[n+0] = a;
- s->buffer[n+1] = b;
- s->buffer[n+2] = c;
+static void stbiw__write3(stbi__write_context* s, unsigned char a, unsigned char b, unsigned char c) {
+ int n;
+ if ((size_t)s->buf_used + 3 > sizeof(s->buffer))
+ stbiw__write_flush(s);
+ n = s->buf_used;
+ s->buf_used = n + 3;
+ s->buffer[n + 0] = a;
+ s->buffer[n + 1] = b;
+ s->buffer[n + 2] = c;
}
-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)
- stbiw__write1(s, d[comp - 1]);
+ if (write_alpha < 0)
+ stbiw__write1(s, d[comp - 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
- stbiw__write1(s, d[0]); // monochrome TGA
- break;
- case 4:
- if (!write_alpha) {
+ else
+ stbiw__write1(s, d[0]); // 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)
- stbiw__write1(s, d[comp - 1]);
+ }
+ /* FALLTHROUGH */
+ case 3:
+ stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
+ break;
+ }
+ if (write_alpha > 0)
+ stbiw__write1(s, d[comp - 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);
- }
- stbiw__write_flush(s);
- 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);
+ }
+ stbiw__write_flush(s);
+ 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)
-{
- if (comp != 4) {
- // write RGB bitmap
- 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
- } else {
- // RGBA bitmaps need a v4 header
- // use BI_BITFIELDS mode with 32bpp and alpha mask
- // (straight BI_RGB with alpha mask doesn't work in most readers)
- return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0,
- "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444",
- 'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header
- 108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header
- }
+static int stbi_write_bmp_core(stbi__write_context* s, int x, int y, int comp, const void* data) {
+ if (comp != 4) {
+ // write RGB bitmap
+ 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
+ } else {
+ // RGBA bitmaps need a v4 header
+ // use BI_BITFIELDS mode with 32bpp and alpha mask
+ // (straight BI_RGB with alpha mask doesn't work in most readers)
+ return stbiw__outfile(s, -1, -1, x, y, comp, 1, (void*)data, 1, 0,
+ "11 4 22 4"
+ "4 44 22 444444 4444 4 444 444 444 444",
+ 'B', 'M', 14 + 108 + x * y * 4, 0, 0, 14 + 108, // file header
+ 108, x, y, 1, 32, 3, 0, 0, 0, 0, 0, 0xff0000, 0xff00, 0xff, 0xff000000u, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0); // bitmap V4 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 = { 0 };
- 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 = {0};
+ 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 = { 0 };
- 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 = {0};
+ 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);
- stbiw__write1(s, header);
- 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);
- stbiw__write1(s, header);
- 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);
+ stbiw__write1(s, header);
+ 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);
+ stbiw__write1(s, header);
+ stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
+ }
}
- }
- }
- stbiw__write_flush(s);
- }
- return 1;
+ }
+ stbiw__write_flush(s);
+ }
+ 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 = { 0 };
- 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 = {0};
+ 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 = { 0 };
- 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 = {0};
+ 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))
#ifndef STBI_WRITE_NO_STDIO
-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;
-
- 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__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;
+
+ 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_LIB_EXT1__
- 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 = { 0 };
- 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 = {0};
+ stbi__start_write_callbacks(&s, func, context);
+ return stbi_write_hdr_core(&s, x, y, comp, (float*)data);
}
-STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
-{
- stbi__write_context s = { 0 };
- 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 = {0};
+ 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 *) (void *) (a) - 2)
-#define stbiw__sbm(a) stbiw__sbraw(a)[0]
-#define stbiw__sbn(a) stbiw__sbraw(a)[1]
+#define stbiw__sbraw(a) ((int*)(void*)(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(unsigned 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(unsigned 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);
-
- // store uncompressed instead if compression was worse
- if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
- stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1
- for (j = 0; j < data_len;) {
- int blocklen = data_len - j;
- if (blocklen > 32767) blocklen = 32767;
- stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression
- stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN
- stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
- stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN
- stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
- memcpy(out+stbiw__sbn(out), data+j, blocklen);
- stbiw__sbn(out) += blocklen;
- j += blocklen;
- }
- }
-
- {
- // 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);
+ }
+
+ 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);
+
+ // store uncompressed instead if compression was worse
+ if (stbiw__sbn(out) > data_len + 2 + ((data_len + 32766) / 32767) * 5) {
+ stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1
+ for (j = 0; j < data_len;) {
+ int blocklen = data_len - j;
+ if (blocklen > 32767)
+ blocklen = 32767;
+ stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression
+ stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN
+ stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
+ stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN
+ stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
+ memcpy(out + stbiw__sbn(out), data + j, blocklen);
+ stbiw__sbn(out) += blocklen;
+ j += blocklen;
+ }
+ }
+
+ {
+ // 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);
#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 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;
+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;
}
-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, int du_stride, 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, j, n, diff, end0pos, x, y;
- int DU[64];
-
- // DCT rows
- for(dataOff=0, n=du_stride*8; dataOff<n; dataOff+=du_stride) {
- 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+du_stride], &CDU[dataOff+du_stride*2], &CDU[dataOff+du_stride*3], &CDU[dataOff+du_stride*4],
- &CDU[dataOff+du_stride*5], &CDU[dataOff+du_stride*6], &CDU[dataOff+du_stride*7]);
- }
- // Quantize/descale/zigzag the coefficients
- for(y = 0, j=0; y < 8; ++y) {
- for(x = 0; x < 8; ++x,++j) {
- float v;
- i = y*du_stride+x;
- v = CDU[i]*fdtbl[j];
- // DU[stbiw__jpg_ZigZag[j]] = (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[j]] = (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, int du_stride,
+ 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, j, n, diff, end0pos, x, y;
+ int DU[64];
+
+ // DCT rows
+ for (dataOff = 0, n = du_stride * 8; dataOff < n; dataOff += du_stride) {
+ 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 + du_stride], &CDU[dataOff + du_stride * 2],
+ &CDU[dataOff + du_stride * 3], &CDU[dataOff + du_stride * 4], &CDU[dataOff + du_stride * 5],
+ &CDU[dataOff + du_stride * 6], &CDU[dataOff + du_stride * 7]);
+ }
+ // Quantize/descale/zigzag the coefficients
+ for (y = 0, j = 0; y < 8; ++y) {
+ for (x = 0; x < 8; ++x, ++j) {
+ float v;
+ i = y * du_stride + x;
+ v = CDU[i] * fdtbl[j];
+ // DU[stbiw__jpg_ZigZag[j]] = (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[j]] = (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, subsample;
- 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;
- subsample = quality <= 90 ? 1 : 0;
- 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,(unsigned char)(subsample?0x22: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};
- 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;
- const unsigned char *dataR = (const unsigned char *)data;
- const unsigned char *dataG = dataR + ofsG;
- const unsigned char *dataB = dataR + ofsB;
- int x, y, pos;
- if(subsample) {
- for(y = 0; y < height; y += 16) {
- for(x = 0; x < width; x += 16) {
- float Y[256], U[256], V[256];
- for(row = y, pos = 0; row < y+16; ++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+16; ++col, ++pos) {
- // if col >= width => use pixel from last input column
- int p = base_p + ((col < width) ? col : (width-1))*comp;
- float r = dataR[p], g = dataG[p], b = dataB[p];
- Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
- U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
- V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
- }
- }
- DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
- DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
- DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
- DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
-
- // subsample U,V
- {
- float subU[64], subV[64];
- int yy, xx;
- for(yy = 0, pos = 0; yy < 8; ++yy) {
- for(xx = 0; xx < 8; ++xx, ++pos) {
- int j = yy*32+xx*2;
- subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f;
- subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f;
- }
- }
- DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
- DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
- }
+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, subsample;
+ 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;
+ subsample = quality <= 90 ? 1 : 0;
+ 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,
+ (unsigned char)(subsample ? 0x22 : 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};
+ 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;
+ const unsigned char* dataR = (const unsigned char*)data;
+ const unsigned char* dataG = dataR + ofsG;
+ const unsigned char* dataB = dataR + ofsB;
+ int x, y, pos;
+ if (subsample) {
+ for (y = 0; y < height; y += 16) {
+ for (x = 0; x < width; x += 16) {
+ float Y[256], U[256], V[256];
+ for (row = y, pos = 0; row < y + 16; ++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 + 16; ++col, ++pos) {
+ // if col >= width => use pixel from last input column
+ int p = base_p + ((col < width) ? col : (width - 1)) * comp;
+ float r = dataR[p], g = dataG[p], b = dataB[p];
+ Y[pos] = +0.29900f * r + 0.58700f * g + 0.11400f * b - 128;
+ U[pos] = -0.16874f * r - 0.33126f * g + 0.50000f * b;
+ V[pos] = +0.50000f * r - 0.41869f * g - 0.08131f * b;
+ }
+ }
+ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y + 0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
+ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y + 8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
+ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y + 128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
+ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y + 136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
+
+ // subsample U,V
+ {
+ float subU[64], subV[64];
+ int yy, xx;
+ for (yy = 0, pos = 0; yy < 8; ++yy) {
+ for (xx = 0; xx < 8; ++xx, ++pos) {
+ int j = yy * 32 + xx * 2;
+ subU[pos] = (U[j + 0] + U[j + 1] + U[j + 16] + U[j + 17]) * 0.25f;
+ subV[pos] = (V[j + 0] + V[j + 1] + V[j + 16] + V[j + 17]) * 0.25f;
+ }
+ }
+ DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
+ DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
+ }
+ }
}
- }
- } else {
- for(y = 0; y < height; y += 8) {
- for(x = 0; x < width; x += 8) {
- float Y[64], U[64], V[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) {
- // if col >= width => use pixel from last input column
- int p = base_p + ((col < width) ? col : (width-1))*comp;
- float r = dataR[p], g = dataG[p], b = dataB[p];
- Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
- U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
- V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
- }
- }
-
- DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT);
- DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
- DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
+ } else {
+ for (y = 0; y < height; y += 8) {
+ for (x = 0; x < width; x += 8) {
+ float Y[64], U[64], V[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) {
+ // if col >= width => use pixel from last input column
+ int p = base_p + ((col < width) ? col : (width - 1)) * comp;
+ float r = dataR[p], g = dataG[p], b = dataB[p];
+ Y[pos] = +0.29900f * r + 0.58700f * g + 0.11400f * b - 128;
+ U[pos] = -0.16874f * r - 0.33126f * g + 0.50000f * b;
+ V[pos] = +0.50000f * r - 0.41869f * g - 0.08131f * b;
+ }
+ }
+
+ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT);
+ DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
+ DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, 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 = { 0 };
- 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 = {0};
+ 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 = { 0 };
- 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 = {0};
+ 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
void TearDown() override {}
void checkPixels(VkvgSurface surf, uint32_t expectedPixelValue) {
- uint32_t w = vkvg_surface_get_width(surf);
- uint32_t h = vkvg_surface_get_height(surf);
+ uint32_t w = vkvg_surface_get_width(surf);
+ uint32_t h = vkvg_surface_get_height(surf);
uint32_t* buff = (uint32_t*)malloc(w * h * sizeof(uint32_t));
vkvg_surface_write_to_memory(surf, (unsigned char*)buff);
vkvg_surface_destroy(surf);
EXPECT_EQ(devRefCntInit, vkvg_device_get_reference_count(dev));
- //EXPECT_EQ(0, vkvg_surface_get_reference_count(surf));
+ // EXPECT_EQ(0, vkvg_surface_get_reference_count(surf));
}
TEST_F(SurfaceTest, SurfProperties) {
EXPECT_EQ(0, vkvg_surface_get_width(NULL));
EXPECT_EQ(VKVG_STATUS_INVALID_STATUS, vkvg_surface_write_to_memory(NULL, NULL));
EXPECT_EQ(VKVG_STATUS_INVALID_STATUS, vkvg_surface_write_to_png(NULL, NULL));
const uint32_t imgSize = 8;
- VkvgSurface surf = vkvg_surface_create(dev, imgSize, imgSize);
+ VkvgSurface surf = vkvg_surface_create(dev, imgSize, imgSize);
EXPECT_EQ(VKVG_STATUS_WRITE_ERROR, vkvg_surface_write_to_memory(surf, NULL));
EXPECT_EQ(VKVG_STATUS_WRITE_ERROR, vkvg_surface_write_to_png(surf, NULL));
- uint32_t buff[imgSize*imgSize];
+ uint32_t buff[imgSize * imgSize];
EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_surface_write_to_memory(surf, (unsigned char*)buff));
vkvg_surface_destroy(surf);
TEST_F(SurfaceTest, SurfClear) {
const uint32_t imgSize = 8;
- VkvgSurface surf = vkvg_surface_create(dev, imgSize, imgSize);
- VkvgContext ctx = vkvg_create(surf);
+ VkvgSurface surf = vkvg_surface_create(dev, imgSize, imgSize);
+ VkvgContext ctx = vkvg_create(surf);
vkvg_set_source_rgb(ctx, 1, 0, 0);
vkvg_paint(ctx);
vkvg_destroy(ctx);
#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
* @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);
+ const char* svgFilePath);
/**
* @brief create surface from svg fragment
*
* @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);
+ 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.
* 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
/**
* 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
*
* 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
*
* @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);
/** @}*/
/*!
* @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.
*
* @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.
* @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 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,
+vkvg_public VkvgSurface vkvg_surface_create_from_bitmap(VkvgDevice dev, unsigned char* img, uint32_t width,
uint32_t height);
/**
* @brief Get the current status of the surface.
* @param path 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 surf The surface to save
* @param bitmap 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.
*
*
* 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.
* @param x2 right of the resulting extents
* @param y2 bottom of the resulting extents
*/
-vkvg_public void vkvg_path_extents(VkvgContext ctx, float* const x1, float *const y1, float *const x2, float *const y2);
+vkvg_public void vkvg_path_extents(VkvgContext ctx, float* const x1, float* const y1, float* const x2, float* const 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 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
* @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
* @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 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.
/**
* @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 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.
*
* @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 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.
*
* @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.
*
* @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.
* @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 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 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_get_data(VkvgRecording rec);
vkvg_public void vkvg_recording_destroy(VkvgRecording rec);
/*************************************/
#endif
#include "SampleApp.hpp"
#include "VkvgTest.hpp"
-
-
-bool SampleApp::try_get_phyinfo(VkhPhyInfo *phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo *phy) {
+bool SampleApp::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 false;
}
-static void glfw_error_callback(int error, const char *description) {
+static void glfw_error_callback(int error, const char* description) {
fprintf(stderr, "vkengine: GLFW error %d: %s\n", error, description);
}
-void SampleApp::key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+void SampleApp::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;
+ // paused = !paused;
break;
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
}
}
-static void char_callback(GLFWwindow *window, uint32_t c) {}
-static void mouse_move_callback(GLFWwindow *window, double x, double y) {}
-static void scroll_callback(GLFWwindow *window, double x, double y) {}
-static void mouse_button_callback(GLFWwindow *window, int but, int state, int modif) {}
-
+static void char_callback(GLFWwindow* window, uint32_t c) {}
+static void mouse_move_callback(GLFWwindow* window, double x, double y) {}
+static void scroll_callback(GLFWwindow* window, double x, double y) {}
+static void mouse_button_callback(GLFWwindow* window, int but, int state, int modif) {}
void SampleApp::Init() {
glfwSetErrorCallback(glfw_error_callback);
perror("glfwVulkanSupported return false.");
exit(-1);
}
- const char *enabledLayers[10];
- const char *enabledExts[10];
+
+ const char* enabledLayers[10];
+ const char* enabledExts[10];
uint32_t enabledExtsCount = 0, enabledLayersCount = 0, phyCount = 0;
vkh_layers_check_init();
vkh_layers_check_release();
uint32_t glfwReqExtsCount = 0;
- const char **gflwExts = glfwGetRequiredInstanceExtensions(&glfwReqExtsCount);
+ const char** gflwExts = glfwGetRequiredInstanceExtensions(&glfwReqExtsCount);
vkvg_get_required_instance_extensions(enabledExts, &enabledExtsCount);
for (uint32_t i = 0; i < glfwReqExtsCount; i++)
enabledExts[i + enabledExtsCount] = gflwExts[i];
-
enabledExtsCount += glfwReqExtsCount;
app = vkh_app_create(1, 2, "vkvg", enabledLayersCount, enabledLayers, enabledExtsCount, enabledExts);
#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
uint32_t severity = 0;
- for(const uint32_t& s : logSeverity)
+ for (const uint32_t& s : logSeverity)
severity += pow(16, s);
- vkh_app_enable_debug_messenger(app,
- (VkDebugUtilsMessageTypeFlagBitsEXT)logType,
- (VkDebugUtilsMessageSeverityFlagBitsEXT)severity,
- NULL);
+ vkh_app_enable_debug_messenger(app, (VkDebugUtilsMessageTypeFlagBitsEXT)logType,
+ (VkDebugUtilsMessageSeverityFlagBitsEXT)severity, NULL);
#endif
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwCreateWindowSurface(vkh_app_get_inst(app), win, NULL, &vkSurf);
- VkhPhyInfo *phys = vkh_app_get_phyinfos(app, &phyCount, vkSurf);
+ VkhPhyInfo* phys = vkh_app_get_phyinfos(app, &phyCount, vkSurf);
if (listGpus) {
std::cout << "Available GPU's:" << std::endl;
TRY_LOAD_DEVICE_EXT(VK_KHR_swapchain)
VkPhysicalDeviceFeatures enabledFeatures{};
- const void *pNext = vkvg_get_device_requirements(&enabledFeatures);
-
- VkDeviceCreateInfo device_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- .pNext = pNext,
- .queueCreateInfoCount = qCount,
- .pQueueCreateInfos = (VkDeviceQueueCreateInfo *)&pQueueInfos,
- .enabledExtensionCount = enabledExtsCount,
- .ppEnabledExtensionNames = enabledExts,
- .pEnabledFeatures = &enabledFeatures,
+ const void* pNext = vkvg_get_device_requirements(&enabledFeatures);
+
+ VkDeviceCreateInfo device_info = {
+ .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ .pNext = pNext,
+ .queueCreateInfoCount = qCount,
+ .pQueueCreateInfos = (VkDeviceQueueCreateInfo*)&pQueueInfos,
+ .enabledExtensionCount = enabledExtsCount,
+ .ppEnabledExtensionNames = enabledExts,
+ .pEnabledFeatures = &enabledFeatures,
};
- vkhDev = vkh_device_create(app, pi, &device_info);
+ vkhDev = vkh_device_create(app, pi, &device_info);
presentQIndex = (uint32_t)pi->pQueue;
- renderer =
- vkh_presenter_create(vkhDev, presentQIndex, vkSurf, width, height, VK_FORMAT_B8G8R8A8_SRGB, presentMode);
-
+ renderer = vkh_presenter_create(vkhDev, presentQIndex, vkSurf, width, height, VK_FORMAT_B8G8R8A8_SRGB, presentMode);
vkh_app_free_phyinfos(phyCount, phys);
glfwSetKeyCallback(win, key_callback);
glfwSetMouseButtonCallback(win, mouse_button_callback);
glfwSetCursorPosCallback(win, mouse_move_callback);
-
}
void SampleApp::Run() {
if (VkvgTest::tests.empty())
return;
- int testIdx = 0;
- auto it = VkvgTest::tests.begin();
+ int testIdx = 0;
+ auto it = VkvgTest::tests.begin();
VkvgTest* curTest = NULL;
if (testsToRun.empty()) {
testIdx++;
curTest->cleanTest();
if (testsToRun.empty()) {
- if (++it == VkvgTest::tests.end()){
+ if (++it == VkvgTest::tests.end()) {
curTest = NULL;
break;
}
#include <GLFW/glfw3.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; \
+ }
class SampleApp {
- bool try_get_phyinfo(VkhPhyInfo *phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo *phy);
+ bool try_get_phyinfo(VkhPhyInfo* phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo* phy);
- static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods);
+ static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
VkPhysicalDeviceMemoryProperties memory_properties;
VkPhysicalDeviceProperties gpu_props;
public:
- uint32_t width = 512;
- uint32_t height = 512;
- uint32_t iterations = 0;
- uint32_t testSize = 500;
+ uint32_t width = 512;
+ uint32_t height = 512;
+ uint32_t iterations = 0;
+ uint32_t testSize = 500;
std::vector<uint32_t> logSeverity = {1};
- uint32_t logType = 0;
- bool listGpus = false;
- int32_t gpuIndex = -1;
- VkSampleCountFlags samples = VK_SAMPLE_COUNT_1_BIT;
+ uint32_t logType = 0;
+ bool listGpus = false;
+ int32_t gpuIndex = -1;
+ VkSampleCountFlags samples = VK_SAMPLE_COUNT_1_BIT;
std::vector<uint32_t> testsToRun;
- VkPhysicalDeviceType preferedGPU = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
- VkPresentModeKHR presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
+ VkPhysicalDeviceType preferedGPU = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
+ VkPresentModeKHR presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
- GLFWwindow* win;
+ GLFWwindow* win;
VkSurfaceKHR vkSurf;
- VkhApp app;
- VkhDevice vkhDev;
+ VkhApp app;
+ VkhDevice vkhDev;
VkhPresenter renderer;
- uint32_t presentQIndex;
+ uint32_t presentQIndex;
void Init();
void Run();
void CleanUp();
};
-
#include "VkvgTest.hpp"
-
std::vector<VkvgTest*> VkvgTest::tests;
VkvgTest::VkvgTest(VkvgTestFunc testFunc, std::string _name) {
this->testFunc = testFunc;
- this->name = _name;
+ this->name = _name;
VkvgTest::tests.push_back(this);
}
void VkvgTest::initTest(SampleApp* app) {
this->app = app;
- vkvg_device_create_info_t info = {
- app->samples, false,
- vkh_app_get_inst(app->app), vkh_device_get_phy(app->vkhDev), vkh_device_get_vkdev(app->vkhDev), app->presentQIndex, 0, false};
+ vkvg_device_create_info_t info = {app->samples,
+ false,
+ vkh_app_get_inst(app->app),
+ vkh_device_get_phy(app->vkhDev),
+ vkh_device_get_vkdev(app->vkhDev),
+ app->presentQIndex,
+ 0,
+ false};
device = vkvg_device_create(&info);
- surf = vkvg_surface_create(device, app->width, app->height);
+ surf = vkvg_surface_create(device, app->width, app->height);
vkvg_device_set_dpy(device, 96, 96);
vkh_presenter_build_blit_cmd(app->renderer, vkvg_surface_get_vk_image(surf), app->width, app->height);
vkDeviceWaitIdle(vkh_device_get_vkdev(app->vkhDev));
}
-void VkvgTest::performTest() {
- testFunc(this);
-}
+void VkvgTest::performTest() { testFunc(this); }
void VkvgTest::cleanTest() {
vkDeviceWaitIdle(vkh_device_get_vkdev(app->vkhDev));
vkvg_surface_destroy(surf);
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 randomize_color(VkvgContext ctx) { vkvg_set_source_rgba(ctx, rndf(), rndf(), rndf(), rndf()); }
void VkvgTest::draw_random_shape(VkvgContext ctx, shape_t shape, float sizeFact) {
float w = (float)app->width;
float h = (float)app->height;
-
float x, y, z, v, r;
randomize_color(ctx);
#include "SampleApp.hpp"
-
#define M_PIF 3.14159265359f /* float pi */
#define M_PIF_MULT_2 6.28318530718f
#ifndef M_PI
} shape_t;
class VkvgTest;
-typedef void (*VkvgTestFunc) (VkvgTest* test);
-
+typedef void (*VkvgTestFunc)(VkvgTest* test);
class VkvgTest {
VkvgTestFunc testFunc;
+
public:
static std::vector<VkvgTest*> tests;
- SampleApp* app;
+ SampleApp* app;
std::string name;
VkvgTest(VkvgTestFunc testFunc, std::string _name);
- VkvgDevice device;
+ VkvgDevice device;
VkvgSurface surf;
-
void initTest(SampleApp* app);
void performTest();
void cleanTest();
void draw_random_curve(VkvgContext ctx);
void draw_random_square(VkvgContext ctx, float s);
};
-#define TEST(name) \
- static void name(VkvgTest* test); \
- static VkvgTest _##name(name, #name); \
- static void name(VkvgTest* test)
+#define TEST(name) \
+ static void name(VkvgTest* test); \
+ static VkvgTest _##name(name, #name); \
+ static void name(VkvgTest* test)
void draw_growing_circles(VkvgContext ctx, float y, int count);
void randomize_color(VkvgContext ctx);
#include "argparse/argparse.hpp"
-int main(int argc, char **argv) {
+int main(int argc, char** argv) {
SampleApp app{};
argparse::ArgumentParser program("samples");
.scan<'u', uint32_t>()
.nargs(argparse::nargs_pattern::at_least_one);
- program.add_argument("--list-tests")
- .help("Get tests list")
- .default_value(false)
- .implicit_value(true);
+ program.add_argument("--list-tests").help("Get tests list").default_value(false).implicit_value(true);
program.add_argument("--list-gpus")
.help("Get available GPU's, select with option '-g'")
.default_value(false)
.implicit_value(true)
.store_into(app.listGpus);
- program.add_argument("-g", "--gpu")
- .help("GPU index")
- .default_value<int32_t>(-1)
- .store_into<int32_t>(app.gpuIndex);
+ program.add_argument("-g", "--gpu").help("GPU index").default_value<int32_t>(-1).store_into<int32_t>(app.gpuIndex);
try {
program.parse_args(argc, argv);
- }
- catch (const std::exception& err) {
+ } catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
app.Init();
app.Run();
-
}
#include "VkvgTest.hpp"
-
//"M80 170 C100 170 160 170 180 170 lZ"
/*TEST(curve2) {
VkvgContext ctx = vkvg_create(test->surf);
}
TEST(long_curv_fill_nz) {
- fillAndStroke = false;
- _long_curv(test,VKVG_FILL_RULE_NON_ZERO);
+ fillAndStroke = false;
+ _long_curv(test, VKVG_FILL_RULE_NON_ZERO);
}
TEST(long_curv_fill_eo) {
fillAndStroke = false;
#include "VkvgTest.hpp"
TEST(img_paint) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror.jpg"));
vkvg_set_source_surface(ctx, imgSurf, 0, 0);
vkvg_destroy(ctx);
}
TEST(img_paint_offset) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror.jpg"));
vkvg_set_source_surface(ctx, imgSurf, 100, 100);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
TEST(img_paint_with_scale) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror.jpg"));
vkvg_scale(ctx, 0.2f, 0.2f);
vkvg_destroy(ctx);
}
TEST(img_translate) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror.jpg"));
vkvg_translate(ctx, 150, 50);
vkvg_set_source_surface(ctx, imgSurf, 0, 0);
vkvg_destroy(ctx);
}
TEST(img_offset_and_scale) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror.jpg"));
vkvg_scale(ctx, 0.2f, 0.2f);
vkvg_set_source_surface(ctx, imgSurf, 100, 100);
static float angle = 0;
TEST(img_paint_with_rot) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror.jpg"));
-
angle += 0.005;
vkvg_clear(ctx);
vkvg_destroy(ctx);
}
TEST(img_offset_and_rot) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror.jpg"));
angle += 0.005;
vkvg_clear(ctx);
vkvg_destroy(ctx);
}
TEST(img_offset_and_rot_center) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror2.png"));
angle += 0.005;
vkvg_clear(ctx);
- vkvg_translate(ctx, 142,142);
+ vkvg_translate(ctx, 142, 142);
vkvg_rotate(ctx, angle);
- vkvg_translate(ctx, -142,-142);
+ vkvg_translate(ctx, -142, -142);
vkvg_set_source_surface(ctx, imgSurf, 100, 100);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
TEST(img_paint_pattern) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror2-64.png"));
VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
vkvg_set_source(ctx, pat);
vkvg_destroy(ctx);
}
TEST(img_paint_patt_repeat) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror.jpg"));
VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
vkvg_pattern_set_extend(pat, VKVG_EXTEND_REPEAT);
vkvg_destroy(ctx);
}
TEST(img_paint_patt_repeat_scalled) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror.jpg"));
vkvg_scale(ctx, 0.2f, 0.2f);
- VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
+ 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_destroy(ctx);
}
TEST(img_paint_patt_pad) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror2-64.png"));
VkvgPattern pat = vkvg_pattern_create_for_surface(imgSurf);
vkvg_pattern_set_extend(pat, VKVG_EXTEND_PAD);
vkvg_destroy(ctx);
}
TEST(imgWithAlphaTest0) {
- VkvgContext ctx = vkvg_create(test->surf);
+ VkvgContext ctx = vkvg_create(test->surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("filled.png"));
vkvg_set_source_surface(ctx, imgSurf, 40, 40);
vkvg_surface_destroy(imgSurf);
}
TEST(imgWithAlphaTest1) {
- VkvgContext ctx = vkvg_create(test->surf);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror.jpg"));
+ VkvgContext ctx = vkvg_create(test->surf);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(test->device, GET_PATH("mirror.jpg"));
VkvgSurface imgSurf2 = vkvg_surface_create_from_image(test->device, GET_PATH("filled.png"));
vkvg_set_source_surface(ctx, imgSurf, 0, 0);
//vkvg_surface_write_to_png(surf, "imgTest4.png");
}*/
-
#include "VkvgTest.hpp"
-
static float shape_size = 0.2f;
void _shape_fill(VkvgTest* test, shape_t shape) {
#include "VkvgTest.hpp"
-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);
}
-void print_boxed(VkvgContext ctx, const char *text, float penX, float penY, uint32_t size) {
+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_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) {
+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_destroy(ctx);
}
-const char *const fonts[] = {"mono", "droid", "times", "arial", "times:bold"};
+const char* const fonts[] = {"mono", "droid", "times", "arial", "times:bold"};
TEST(text_random_font_and_size) {
VkvgContext ctx = vkvg_create(test->surf);
#define _CRT_SECURE_NO_WARNINGS
-int directoryExists(const char *path) {
+int directoryExists(const char* path) {
#if defined(_WIN32) || defined(_WIN64)
#elif __APPLE__
#elif __unix__
return -1;
#endif
}
-const char *getUserDir() {
+const char* getUserDir() {
#if defined(_WIN32) || defined(_WIN64)
return getenv("HOME");
#elif __APPLE__
#elif __unix__
- struct passwd *pw = getpwuid(getuid());
+ struct passwd* pw = getpwuid(getuid());
return pw->pw_dir;
#endif
}
#include <unistd.h>
void handler(int sig) {
- void *array[100];
+ void* array[100];
size_t size;
// get void*'s for all entries on the stack
#endif
#endif
-const char *getUserDir();
+const char* getUserDir();
/* Standard, good-to-have defines */
#ifndef NULL
-#define NULL (void *)0
+#define NULL (void*)0
#endif
#ifndef TRUE
#define TRUE 1
#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;
#endif
}
-void mtx_destroy(mtx_t *mtx) {
+void mtx_destroy(mtx_t* mtx) {
#if defined(_TTHREAD_WIN32_)
DeleteCriticalSection(&mtx->mHandle);
#else
#endif
}
-int mtx_lock(mtx_t *mtx) {
+int mtx_lock(mtx_t* mtx) {
#if defined(_TTHREAD_WIN32_)
EnterCriticalSection(&mtx->mHandle);
if (!mtx->mRecursive) {
#endif
}
-int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) {
+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) {
#endif
}
-int mtx_unlock(mtx_t *mtx) {
+int mtx_unlock(mtx_t* mtx) {
#if defined(_TTHREAD_WIN32_)
mtx->mAlreadyLocked = FALSE;
LeaveCriticalSection(&mtx->mHandle);
#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;
#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]);
#endif
}
-int cnd_signal(cnd_t *cond) {
+int cnd_signal(cnd_t* cond) {
#if defined(_TTHREAD_WIN32_)
int haveWaiters;
#endif
}
-int cnd_broadcast(cnd_t *cond) {
+int cnd_broadcast(cnd_t* cond) {
#if defined(_TTHREAD_WIN32_)
int haveWaiters;
}
#if defined(_TTHREAD_WIN32_)
-static int _cnd_timedwait_win32(cnd_t *cond, mtx_t *mtx, DWORD timeout) {
+static int _cnd_timedwait_win32(cnd_t* cond, mtx_t* mtx, DWORD timeout) {
int result, lastWaiter;
/* Increment number of waiters */
}
#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);
#else
#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) {
/** 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. */
+ 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;
+ 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;
+ _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);
+ free((void*)ti);
/* Call the actual client thread function */
res = fun(arg);
#else
pres = malloc(sizeof(int));
if (pres != NULL) {
- *(int *)pres = res;
+ *(int*)pres = res;
}
return pres;
#endif
}
-int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) {
+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));
+ _thread_start_info* ti = (_thread_start_info*)malloc(sizeof(_thread_start_info));
if (ti == NULL) {
return thrd_nomem;
}
/* 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) {
+ if (pthread_create(thr, NULL, _thrd_wrapper_function, (void*)ti) != 0) {
*thr = 0;
}
#endif
#if defined(_TTHREAD_WIN32_)
ExitThread(res);
#else
- void *pres = malloc(sizeof(int));
+ void* pres = malloc(sizeof(int));
if (pres != NULL) {
- *(int *)pres = res;
+ *(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;
*res = dwRes;
}
#elif defined(_TTHREAD_POSIX_)
- void *pres;
+ void* pres;
int ires = 0;
if (pthread_join(thr, &pres) != 0) {
return thrd_error;
}
if (pres != NULL) {
- ires = *(int *)pres;
+ ires = *(int*)pres;
free(pres);
}
if (res != NULL) {
return thrd_success;
}
-int thrd_sleep(const struct timespec *time_point, struct timespec *remaining) {
+int thrd_sleep(const struct timespec* time_point, struct timespec* remaining) {
struct timespec now;
#if defined(_TTHREAD_WIN32_)
DWORD delta;
#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) {
#endif
}
-void *tss_get(tss_t key) {
+void* tss_get(tss_t key) {
#if defined(_TTHREAD_WIN32_)
return TlsGetValue(key);
#else
#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 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);
#define clockid_t _tthread_clockid_t
/* 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);
#define clock_gettime _tthread_clock_gettime
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
* @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);
+int mtx_init(mtx_t* mtx, int type);
/** Release any resources used by the given mutex.
* @param mtx A mutex object.
*/
-void mtx_destroy(mtx_t *mtx);
+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
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
-int mtx_lock(mtx_t *mtx);
+int mtx_lock(mtx_t* mtx);
/** NOT YET IMPLEMENTED.
*/
-int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
+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
* requested is already in use, or @ref thrd_error if the request could not be
* honored.
*/
-int mtx_trylock(mtx_t *mtx);
+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.
*/
-int mtx_unlock(mtx_t *mtx);
+int mtx_unlock(mtx_t* mtx);
/* Condition variable */
#if defined(_TTHREAD_WIN32_)
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.
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
-int cnd_init(cnd_t *cond);
+int cnd_init(cnd_t* cond);
/** Release any resources used by the given condition variable.
* @param cond A condition variable object.
*/
-void cnd_destroy(cnd_t *cond);
+void cnd_destroy(cnd_t* cond);
/** Signal a condition variable.
* Unblocks one of the threads that are blocked on the given condition variable
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
-int cnd_signal(cnd_t *cond);
+int cnd_signal(cnd_t* cond);
/** Broadcast a condition variable.
* Unblocks all of the threads that are blocked on the given condition variable
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
-int cnd_broadcast(cnd_t *cond);
+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
* @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);
+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
* 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);
+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.
* @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);
+typedef int (*thrd_start_t)(void* arg);
/** Create a new thread.
* @param thr Identifier of the newly created thread.
* 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);
+int thrd_create(thrd_t* thr, thrd_start_t func, void* arg);
/** Identify the calling thread.
* @return The identifier of the calling thread.
* @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);
+int thrd_join(thrd_t thr, int* res);
/** Put the calling thread to sleep.
* Suspend execution of the calling thread.
* time.
* @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
*/
-int thrd_sleep(const struct timespec *time_point, struct timespec *remaining);
+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
#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.
*/
-typedef void (*tss_dtor_t)(void *val);
+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
* 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);
+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
* @return The value for the current thread held in the given thread-specific
* storage.
*/
-void *tss_get(tss_t key);
+void* tss_get(tss_t key);
/** Set the value for a thread-specific storage.
* @param key The thread-specific storage identifier.
* @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);
+int tss_set(tss_t key, void* val);
#endif /* _TINYTHREAD_H_ */
char type;
union {
unsigned int color;
- NSVGgradient *gradient;
+ NSVGgradient* gradient;
};
} NSVGpaint;
typedef struct NSVGpath {
- float *pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
+ 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.
+ struct NSVGpath* next; // Pointer to next path, or NULL if last element.
} NSVGpath;
typedef struct NSVGshape {
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.
+ 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.
+ 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
#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) {
+static void nsvg__parseContent(char* s, void (*contentCb)(void* ud, const char* s), void* ud) {
// Trim start white spaces
while (nsvg__isspace(*s))
s++;
(*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];
+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;
+ char* name;
int start = 0;
int end = 0;
char quote;
// Get attribs
while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS - 3) {
- char *name = NULL;
- char *value = NULL;
+ char* name = NULL;
+ char* value = NULL;
// Skip white space before the attrib name
while (nsvg__isspace(*s))
(*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 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) {
char units;
float xform[6];
int nstops;
- NSVGgradientStop *stops;
- struct NSVGgradientData *next;
+ NSVGgradientStop* stops;
+ struct NSVGgradientData* next;
} NSVGgradientData;
typedef struct NSVGattrib {
typedef struct NSVGparser {
NSVGattrib attr[NSVG_MAX_ATTR];
int attrHead;
- float *pts;
+ float* pts;
int npts;
int cpts;
- NSVGpath *plist;
- NSVGimage *image;
- NSVGgradientData *gradients;
- NSVGshape *shapesTail;
+ NSVGpath* plist;
+ NSVGimage* image;
+ NSVGgradientData* gradients;
+ NSVGshape* shapesTail;
float viewMinx, viewMiny, viewWidth, viewHeight;
int alignX, alignY, alignType;
float dpi;
char defsFlag;
} NSVGparser;
-static void nsvg__xformIdentity(float *t) {
+static void nsvg__xformIdentity(float* t) {
t[0] = 1.0f;
t[1] = 0.0f;
t[2] = 0.0f;
t[5] = 0.0f;
}
-static void nsvg__xformSetTranslation(float *t, float tx, float ty) {
+static void nsvg__xformSetTranslation(float* t, float tx, float ty) {
t[0] = 1.0f;
t[1] = 0.0f;
t[2] = 0.0f;
t[5] = ty;
}
-static void nsvg__xformSetScale(float *t, float sx, float sy) {
+static void nsvg__xformSetScale(float* t, float sx, float sy) {
t[0] = sx;
t[1] = 0.0f;
t[2] = 0.0f;
t[5] = 0.0f;
}
-static void nsvg__xformSetSkewX(float *t, float a) {
+static void nsvg__xformSetSkewX(float* t, float a) {
t[0] = 1.0f;
t[1] = 0.0f;
t[2] = tanf(a);
t[5] = 0.0f;
}
-static void nsvg__xformSetSkewY(float *t, float a) {
+static void nsvg__xformSetSkewY(float* t, float a) {
t[0] = 1.0f;
t[1] = tanf(a);
t[2] = 0.0f;
t[5] = 0.0f;
}
-static void nsvg__xformSetRotation(float *t, float a) {
+static void nsvg__xformSetRotation(float* t, float a) {
float cs = cosf(a), sn = sinf(a);
t[0] = cs;
t[1] = sn;
t[5] = 0.0f;
}
-static void nsvg__xformMultiply(float *t, float *s) {
+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[4] = t4;
}
-static void nsvg__xformInverse(float *inv, float *t) {
+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);
inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
}
-static void nsvg__xformPremultiply(float *t, float *s) {
+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) {
+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) {
+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) {
+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];
}
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) {
+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];
+ 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]);
}
}
-static NSVGparser *nsvg__createParser() {
- NSVGparser *p;
- p = (NSVGparser *)malloc(sizeof(NSVGparser));
+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));
+ p->image = (NSVGimage*)malloc(sizeof(NSVGimage));
if (p->image == NULL)
goto error;
memset(p->image, 0, sizeof(NSVGimage));
return NULL;
}
-static void nsvg__deletePaths(NSVGpath *path) {
+static void nsvg__deletePaths(NSVGpath* path) {
while (path) {
- NSVGpath *next = path->next;
+ NSVGpath* next = path->next;
if (path->pts != NULL)
free(path->pts);
free(path);
}
}
-static void nsvg__deletePaint(NSVGpaint *paint) {
+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__deleteGradientData(NSVGgradientData *grad) {
- NSVGgradientData *next;
+static void nsvg__deleteGradientData(NSVGgradientData* grad) {
+ NSVGgradientData* next;
while (grad != NULL) {
next = grad->next;
free(grad->stops);
}
}
-static void nsvg__deleteParser(NSVGparser *p) {
+static void nsvg__deleteParser(NSVGparser* p) {
if (p != NULL) {
nsvg__deletePaths(p->plist);
nsvg__deleteGradientData(p->gradients);
}
}
-static void nsvg__resetPath(NSVGparser *p) { p->npts = 0; }
+static void nsvg__resetPath(NSVGparser* p) { p->npts = 0; }
-static void nsvg__addPoint(NSVGparser *p, float x, float y) {
+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));
+ p->pts = (float*)realloc(p->pts, p->cpts * 2 * sizeof(float));
if (!p->pts)
return;
}
p->npts++;
}
-static void nsvg__moveTo(NSVGparser *p, float x, float y) {
+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;
}
}
-static void nsvg__lineTo(NSVGparser *p, float x, float 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];
}
}
-static void nsvg__cubicBezTo(NSVGparser *p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float 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 NSVGattrib* nsvg__getAttr(NSVGparser* p) { return &p->attr[p->attrHead]; }
-static void nsvg__pushAttr(NSVGparser *p) {
+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) {
+static void nsvg__popAttr(NSVGparser* p) {
if (p->attrHead > 0)
p->attrHead--;
}
-static float nsvg__actualOrigX(NSVGparser *p) { return p->viewMinx; }
+static float nsvg__actualOrigX(NSVGparser* p) { return p->viewMinx; }
-static float nsvg__actualOrigY(NSVGparser *p) { return p->viewMiny; }
+static float nsvg__actualOrigY(NSVGparser* p) { return p->viewMiny; }
-static float nsvg__actualWidth(NSVGparser *p) { return p->viewWidth; }
+static float nsvg__actualWidth(NSVGparser* p) { return p->viewWidth; }
-static float nsvg__actualHeight(NSVGparser *p) { return p->viewHeight; }
+static float nsvg__actualHeight(NSVGparser* p) { return p->viewHeight; }
-static float nsvg__actualLength(NSVGparser *p) {
+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);
+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;
return c.value;
}
-static NSVGgradientData *nsvg__findGradientData(NSVGparser *p, const char *id) {
- NSVGgradientData *grad = p->gradients;
+static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id) {
+ NSVGgradientData* grad = p->gradients;
while (grad) {
if (strcmp(grad->id, id) == 0)
return grad;
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;
+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;
if (stops == NULL)
return NULL;
- grad = (NSVGgradient *)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop) * (nstops - 1));
+ grad = (NSVGgradient*)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop) * (nstops - 1));
if (grad == NULL)
return NULL;
return grad;
}
-static float nsvg__getAverageScale(float *t) {
+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;
+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) {
}
}
-static void nsvg__addShape(NSVGparser *p) {
- NSVGattrib *attr = nsvg__getAttr(p);
+static void nsvg__addShape(NSVGparser* p) {
+ NSVGattrib* attr = nsvg__getAttr(p);
float scale = 1.0f;
- NSVGshape *shape;
- NSVGpath *path;
+ NSVGshape* shape;
+ NSVGpath* path;
int i;
if (p->plist == NULL)
return;
- shape = (NSVGshape *)malloc(sizeof(NSVGshape));
+ shape = (NSVGshape*)malloc(sizeof(NSVGshape));
if (shape == NULL)
goto error;
memset(shape, 0, sizeof(NSVGshape));
free(shape);
}
-static void nsvg__addPath(NSVGparser *p, char closed) {
- NSVGattrib *attr = nsvg__getAttr(p);
- NSVGpath *path = NULL;
+static void nsvg__addPath(NSVGparser* p, char closed) {
+ NSVGattrib* attr = nsvg__getAttr(p);
+ NSVGpath* path = NULL;
float bounds[4];
- float *curve;
+ float* curve;
int i;
if (p->npts < 4)
if (closed)
nsvg__lineTo(p, p->pts[0], p->pts[1]);
- path = (NSVGpath *)malloc(sizeof(NSVGpath));
+ path = (NSVGpath*)malloc(sizeof(NSVGpath));
if (path == NULL)
goto error;
memset(path, 0, sizeof(NSVGpath));
- path->pts = (float *)malloc(p->npts * 2 * sizeof(float));
+ path->pts = (float*)malloc(p->npts * 2 * sizeof(float));
if (path->pts == NULL)
goto error;
path->closed = closed;
}
// 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;
+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;
return res * sign;
}
-static const char *nsvg__parseNumber(const char *s, char *it, const int size) {
+static const char* nsvg__parseNumber(const char* s, char* it, const int size) {
const int last = size - 1;
int i = 0;
return s;
}
-static const char *nsvg__getNextPathItemWhenArcFlag(const char *s, char *it) {
+static const char* nsvg__getNextPathItemWhenArcFlag(const char* s, char* it) {
it[0] = '\0';
while (nsvg__isspace(*s) || *s == ',')
s++;
return s;
}
-static const char *nsvg__getNextPathItem(const char *s, char *it) {
+static const char* nsvg__getNextPathItem(const char* s, char* it) {
it[0] = '\0';
// Skip white spaces and commas
while (nsvg__isspace(*s) || *s == ',')
return s;
}
-static unsigned int nsvg__parseColorHex(const char *str) {
+static unsigned int nsvg__parseColorHex(const char* str) {
unsigned int c = 0, r = 0, g = 0, b = 0;
int n = 0;
str++; // skip #
return NSVG_RGB(r, g, b);
}
-static unsigned int nsvg__parseColorRGB(const char *str) {
+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);
}
typedef struct NSVGNamedColor {
- const char *name;
+ const char* name;
unsigned int color;
} NSVGNamedColor;
#endif
};
-static unsigned int nsvg__parseColorName(const char *str) {
+static unsigned int nsvg__parseColorName(const char* str) {
int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);
for (i = 0; i < ncolors; i++) {
return NSVG_RGB(128, 128, 128);
}
-static unsigned int nsvg__parseColor(const char *str) {
+static unsigned int nsvg__parseColor(const char* str) {
size_t len = 0;
while (*str == ' ')
++str;
return nsvg__parseColorName(str);
}
-static float nsvg__parseOpacity(const char *str) {
+static float nsvg__parseOpacity(const char* str) {
float val = nsvg__atof(str);
if (val < 0.0f)
val = 0.0f;
return val;
}
-static float nsvg__parseMiterLimit(const char *str) {
+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) {
+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_USER;
}
-static NSVGcoordinate nsvg__parseCoordinateRaw(const char *str) {
+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));
return coord;
}
-static float nsvg__parseCoordinate(NSVGparser *p, const char *str, float orig, float length) {
+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;
+static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na) {
+ const char* end;
+ const char* ptr;
char it[64];
*na = 0;
return (int)(end - str);
}
-static int nsvg__parseMatrix(float *xform, const char *str) {
+static int nsvg__parseMatrix(float* xform, const char* str) {
float t[6];
int na = 0;
int len = nsvg__parseTransformArgs(str, t, 6, &na);
return len;
}
-static int nsvg__parseTranslate(float *xform, const char *str) {
+static int nsvg__parseTranslate(float* xform, const char* str) {
float args[2];
float t[6];
int na = 0;
return len;
}
-static int nsvg__parseScale(float *xform, const char *str) {
+static int nsvg__parseScale(float* xform, const char* str) {
float args[2];
int na = 0;
float t[6];
return len;
}
-static int nsvg__parseSkewX(float *xform, const char *str) {
+static int nsvg__parseSkewX(float* xform, const char* str) {
float args[1];
int na = 0;
float t[6];
return len;
}
-static int nsvg__parseSkewY(float *xform, const char *str) {
+static int nsvg__parseSkewY(float* xform, const char* str) {
float args[1];
int na = 0;
float t[6];
return len;
}
-static int nsvg__parseRotate(float *xform, const char *str) {
+static int nsvg__parseRotate(float* xform, const char* str) {
float args[3];
int na = 0;
float m[6];
return len;
}
-static void nsvg__parseTransform(float *xform, const char *str) {
+static void nsvg__parseTransform(float* xform, const char* str) {
float t[6];
nsvg__xformIdentity(xform);
while (*str) {
}
}
-static void nsvg__parseUrl(char *id, const char *str) {
+static void nsvg__parseUrl(char* id, const char* str) {
int i = 0;
str += 4; // "url(";
if (*str == '#')
id[i] = '\0';
}
-static char nsvg__parseLineCap(const char *str) {
+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_BUTT;
}
-static char nsvg__parseLineJoin(const char *str) {
+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_MITER;
}
-static char nsvg__parseFillRule(const char *str) {
+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_NONZERO;
}
-static const char *nsvg__getNextDashItem(const char *s, char *it) {
+static const char* nsvg__getNextDashItem(const char* s, char* it) {
int n = 0;
it[0] = '\0';
// Skip white spaces and commas
return s;
}
-static int nsvg__parseStrokeDashArray(NSVGparser *p, const char *str, float *strokeDashArray) {
+static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray) {
char item[64];
int count = 0, i;
float sum = 0.0f;
return count;
}
-static void nsvg__parseStyle(NSVGparser *p, const char *str);
+static void nsvg__parseStyle(NSVGparser* p, const char* str);
-static int nsvg__parseAttr(NSVGparser *p, const char *name, const char *value) {
+static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value) {
float xform[6];
- NSVGattrib *attr = nsvg__getAttr(p);
+ NSVGattrib* attr = nsvg__getAttr(p);
if (!attr)
return 0;
return 1;
}
-static int nsvg__parseNameValue(NSVGparser *p, const char *start, const char *end) {
- const char *str;
- const char *val;
+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;
return nsvg__parseAttr(p, name, value);
}
-static void nsvg__parseStyle(NSVGparser *p, const char *str) {
- const char *start;
- const char *end;
+static void nsvg__parseStyle(NSVGparser* p, const char* str) {
+ const char* start;
+ const char* end;
while (*str) {
// Left Trim
}
}
-static void nsvg__parseAttribs(NSVGparser *p, const char **attr) {
+static void nsvg__parseAttribs(NSVGparser* p, const char** attr) {
int i;
for (i = 0; attr[i]; i += 2) {
if (strcmp(attr[i], "style") == 0)
return 0;
}
-static void nsvg__pathMoveTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) {
if (rel) {
*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) {
+static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) {
if (rel) {
*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) {
+static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) {
if (rel)
*cpx += args[0];
else
nsvg__lineTo(p, *cpx, *cpy);
}
-static void nsvg__pathVLineTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) {
if (rel)
*cpy += args[0];
else
nsvg__lineTo(p, *cpx, *cpy);
}
-static void nsvg__pathCubicBezTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+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;
*cpy = y2;
}
-static void nsvg__pathCubicBezShortTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+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;
*cpy = y2;
}
-static void nsvg__pathQuadBezTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args, int rel) {
+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;
*cpy = y2;
}
-static void nsvg__pathQuadBezShortTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+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;
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) {
+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;
*cpy = y2;
}
-static void nsvg__parsePath(NSVGparser *p, const char **attr) {
- const char *s = NULL;
+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];
+ const char* tmp[4];
char closedFlag;
int i;
char item[64];
nsvg__addShape(p);
}
-static void nsvg__parseRect(NSVGparser *p, const char **attr) {
+static void nsvg__parseRect(NSVGparser* p, const char** attr) {
float x = 0.0f;
float y = 0.0f;
float w = 0.0f;
}
}
-static void nsvg__parseCircle(NSVGparser *p, const char **attr) {
+static void nsvg__parseCircle(NSVGparser* p, const char** attr) {
float cx = 0.0f;
float cy = 0.0f;
float r = 0.0f;
}
}
-static void nsvg__parseEllipse(NSVGparser *p, const char **attr) {
+static void nsvg__parseEllipse(NSVGparser* p, const char** attr) {
float cx = 0.0f;
float cy = 0.0f;
float rx = 0.0f;
}
}
-static void nsvg__parseLine(NSVGparser *p, const char **attr) {
+static void nsvg__parseLine(NSVGparser* p, const char** attr) {
float x1 = 0.0;
float y1 = 0.0;
float x2 = 0.0;
nsvg__addShape(p);
}
-static void nsvg__parsePoly(NSVGparser *p, const char **attr, int closeFlag) {
+static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag) {
int i;
- const char *s;
+ const char* s;
float args[2];
int nargs, npts = 0;
char item[64];
nsvg__addShape(p);
}
-static void nsvg__parseSVG(NSVGparser *p, const char **attr) {
+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])) {
} 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];
+ const char* s = attr[i + 1];
char buf[64];
s = nsvg__parseNumber(s, buf, 64);
p->viewMinx = nsvg__atof(buf);
}
}
-static void nsvg__parseGradient(NSVGparser *p, const char **attr, char type) {
+static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type) {
int i;
- NSVGgradientData *grad = (NSVGgradientData *)malloc(sizeof(NSVGgradientData));
+ NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData));
if (grad == NULL)
return;
memset(grad, 0, sizeof(NSVGgradientData));
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];
+ const char* href = attr[i + 1];
strncpy(grad->ref, href + 1, 62);
grad->ref[62] = '\0';
}
p->gradients = grad;
}
-static void nsvg__parseGradientStop(NSVGparser *p, const char **attr) {
- NSVGattrib *curAttr = nsvg__getAttr(p);
- NSVGgradientData *grad;
- NSVGgradientStop *stop;
+static void nsvg__parseGradientStop(NSVGparser* p, const char** attr) {
+ NSVGattrib* curAttr = nsvg__getAttr(p);
+ NSVGgradientData* grad;
+ NSVGgradientStop* stop;
int i, idx;
curAttr->stopOffset = 0;
return;
grad->nstops++;
- grad->stops = (NSVGgradientStop *)realloc(grad->stops, sizeof(NSVGgradientStop) * grad->nstops);
+ grad->stops = (NSVGgradientStop*)realloc(grad->stops, sizeof(NSVGgradientStop) * grad->nstops);
if (grad->stops == NULL)
return;
stop->offset = curAttr->stopOffset;
}
-static void nsvg__startElement(void *ud, const char *el, const char **attr) {
- NSVGparser *p = (NSVGparser *)ud;
+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
}
}
-static void nsvg__endElement(void *ud, const char *el) {
- NSVGparser *p = (NSVGparser *)ud;
+static void nsvg__endElement(void* ud, const char* el) {
+ NSVGparser* p = (NSVGparser*)ud;
if (strcmp(el, "g") == 0) {
nsvg__popAttr(p);
}
}
-static void nsvg__content(void *ud, const char *s) {
+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;
+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 (container - content) * 0.5f;
}
-static void nsvg__scaleGradient(NSVGgradient *grad, float tx, float ty, float sx, float sy) {
+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__xformMultiply(grad->xform, t);
}
-static void nsvg__scaleToViewbox(NSVGparser *p, const char *units) {
- NSVGshape *shape;
- NSVGpath *path;
+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;
+ float* pt;
// Guess image size if not set completely.
nsvg__imageBounds(p, bounds);
}
}
-NSVGimage *nsvgParse(char *input, const char *units, float dpi) {
- NSVGparser *p;
- NSVGimage *ret = 0;
+NSVGimage* nsvgParse(char* input, const char* units, float dpi) {
+ NSVGparser* p;
+ NSVGimage* ret = 0;
p = nsvg__createParser();
if (p == NULL) {
return ret;
}
-NSVGimage *nsvgParseFromFile(const char *filename, const char *units, float dpi) {
- FILE *fp = NULL;
+NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi) {
+ FILE* fp = NULL;
size_t size;
- char *data = NULL;
- NSVGimage *image = NULL;
+ char* data = NULL;
+ NSVGimage* image = NULL;
fp = fopen(filename, "rb");
if (!fp)
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
- data = (char *)malloc(size + 1);
+ data = (char*)malloc(size + 1);
if (data == NULL)
goto error;
if (fread(data, 1, size, fp) != size)
return NULL;
}
-NSVGpath *nsvgDuplicatePath(NSVGpath *p) {
- NSVGpath *res = NULL;
+NSVGpath* nsvgDuplicatePath(NSVGpath* p) {
+ NSVGpath* res = NULL;
if (p == NULL)
return NULL;
- res = (NSVGpath *)malloc(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));
+ 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);
return NULL;
}
-void nsvgDelete(NSVGimage *image) {
+void nsvgDelete(NSVGimage* image) {
NSVGshape *snext, *shape;
if (image == NULL)
return;
vkvg_set_source_rgba(ctx, r, g, b, a * alpha);
}
-VkvgSurface _svg_load(VkvgDevice dev, NSVGimage *svg) {
+VkvgSurface _svg_load(VkvgDevice dev, NSVGimage* svg) {
if (svg == NULL) {
LOG(VKVG_LOG_ERR, "nsvg error");
return NULL;
return surf;
}
-VkvgSurface vkvg_surface_create_from_svg(VkvgDevice dev, uint32_t width, uint32_t height, const char *filePath) {
+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) {
+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); }
+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) {
+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;
+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_line_width(ctx, shape->strokeWidth);
for (path = shape->paths; path != NULL; path = path->next) {
- float *p = path->pts;
+ 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];
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;
+ NSVGgradient* g = shape->fill.gradient;
_svg_set_color(ctx, g->stops[0].color, o);
}
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;
+ NSVGgradient* g = shape->stroke.gradient;
_svg_set_color(ctx, g->stops[0].color, o);
}
return 0;
return rec->commandsCount;
}
-void *vkvg_recording_get_data(VkvgRecording rec) {
+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) {
+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;
+ *dataOffset = (void*)rec->commands[cmdIndex].dataOffset;
} else {
*cmd = 0;
*dataOffset = NULL;
#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->commands = (vkvg_record_t*)malloc(rec->commandsReservedCount * sizeof(vkvg_record_t));
rec->buffer = malloc(rec->bufferReservedSize);
return rec;
}
-void _destroy_recording(vkvg_recording_t *rec) {
+void _destroy_recording(vkvg_recording_t* rec) {
if (!rec)
return;
for (uint32_t i = 0; i < rec->commandsCount; i++) {
_destroy_recording(ctx->recording);
ctx->recording = _new_recording();
}
-vkvg_recording_t *_stop_recording(VkvgContext ctx) {
- vkvg_recording_t *rec = ctx->recording;
+vkvg_recording_t* _stop_recording(VkvgContext ctx) {
+ vkvg_recording_t* rec = ctx->recording;
if (!rec)
return NULL;
if (!rec->commandsCount) {
ctx->recording = NULL;
return rec;
}
-void *_ensure_recording_buffer(vkvg_recording_t *rec, size_t size) {
+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) {
+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)); \
+ 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); \
+ 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)); \
+ 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, ...) {
+void _record(vkvg_recording_t* rec, ...) {
va_list args;
va_start(args, rec);
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));
+ rec->commands = (vkvg_record_t*)realloc(rec->commands, rec->commandsReservedCount * sizeof(vkvg_record_t));
}
- vkvg_record_t *r = &rec->commands[rec->commandsCount++];
+ vkvg_record_t* r = &rec->commands[rec->commandsCount++];
r->cmd = cmd;
r->dataOffset = rec->bufferSize;
- char *buff;
+ char* buff;
int i = 0;
if (cmd & VKVG_CMD_PATH_COMMANDS) {
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 *);
+ 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));
buff = _ensure_recording_buffer(rec, sizeof(VkvgPattern));
VkvgPattern pat = (VkvgPattern)va_arg(args, VkvgPattern);
vkvg_pattern_reference(pat);
- VkvgPattern *pPat = (VkvgPattern *)buff;
+ VkvgPattern* pPat = (VkvgPattern*)buff;
*pPat = pat;
_advance_recording_buffer_unchecked(rec, sizeof(VkvgPattern));
} break;
buff = _ensure_recording_buffer(rec, sizeof(VkvgSurface));
VkvgSurface surf = (VkvgSurface)va_arg(args, VkvgSurface);
vkvg_surface_reference(surf);
- *(VkvgSurface *)buff = surf;
+ *(VkvgSurface*)buff = surf;
_advance_recording_buffer_unchecked(rec, sizeof(VkvgSurface));
}
break;
}
} else if (r->cmd & VKVG_CMD_TEXT_COMMANDS) {
- char *txt;
+ char* txt;
int txtLen;
switch (r->cmd) {
case VKVG_CMD_SET_FONT_SIZE:
break;
case VKVG_CMD_SHOW_TEXT:
case VKVG_CMD_SET_FONT_FACE:
- txt = (char *)va_arg(args, char *);
+ txt = (char*)va_arg(args, char*);
txtLen = strlen(txt);
buff = _ensure_recording_buffer(rec, txtLen * sizeof(char));
strcpy(buff, txt);
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;
+ 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) {
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];
+ 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]);
}
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];
+ 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;
vkvg_identity_matrix(ctx);
return;
case VKVG_CMD_TRANSFORM: {
- vkvg_matrix_t *mat = (vkvg_matrix_t *)&floats[0];
+ 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_matrix_t* mat = (vkvg_matrix_t*)&floats[0];
vkvg_set_matrix(ctx, mat);
}
return;
vkvg_set_source_color(ctx, uints[0]);
return;
case VKVG_CMD_SET_SOURCE: {
- VkvgPattern pat = *((VkvgPattern *)(rec->buffer + r->dataOffset));
+ VkvgPattern pat = *((VkvgPattern*)(rec->buffer + r->dataOffset));
vkvg_set_source(ctx, pat);
}
return;
case VKVG_CMD_SET_SOURCE_SURFACE: {
- VkvgSurface surf = *((VkvgSurface *)&floats[2]);
+ 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;
+ char* txt = (char*)floats;
switch (r->cmd) {
case VKVG_CMD_SET_FONT_SIZE:
vkvg_set_font_size(ctx, uints[0]);
} vkvg_record_t;
typedef struct _vkvg_recording_t {
- vkvg_record_t *commands;
+ vkvg_record_t* commands;
uint32_t commandsCount;
uint32_t commandsReservedCount;
size_t bufferSize;
size_t bufferReservedSize;
- char *buffer;
+ char* buffer;
} vkvg_recording_t;
void _start_recording(VkvgContext ctx);
-vkvg_recording_t *_stop_recording(VkvgContext ctx);
-void _destroy_recording(vkvg_recording_t *rec);
+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, ...);
+void _record(vkvg_recording_t* rec, ...);
#define RECORD(ctx, ...) \
{ \
//
typedef struct {
- int (*read)(void *user, char *data,
+ 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
+ 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,
+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_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,
+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_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_from_file_16(FILE *f, 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,
+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_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);
+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
#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,
// 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,
+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(const char *buffer, int len, int *outlen);
-STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
+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 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 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);
#ifdef __cplusplus
}
int img_n, img_out_n;
stbi_io_callbacks io;
- void *io_user_data;
+ void* io_user_data;
int read_from_callbacks;
int buflen;
stbi_uc *img_buffer_original, *img_buffer_original_end;
} stbi__context;
-static void stbi__refill_buffer(stbi__context *s);
+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) {
+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;
+ 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) {
+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);
#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_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) { }
#endif // !STBI_NO_STDIO
-static void stbi__rewind(stbi__context *s) {
+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
} 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;
+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) {
+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
#endif
// mallocs with size overflow checking
-static void *stbi__malloc_mad2(int a, int b, int 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) {
+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) {
+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);
#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;
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,
+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
#ifndef STBI_NO_HDR
if (stbi__hdr_test(s)) {
- float *hdr = stbi__hdr_load(s, x, y, comp, req_comp, ri);
+ 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
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) {
+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;
+ stbi_uc* reduced;
- reduced = (stbi_uc *)stbi__malloc(img_len);
+ reduced = (stbi_uc*)stbi__malloc(img_len);
if (reduced == NULL)
return stbi__errpuc("outofmem", "Out of memory");
return reduced;
}
-static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) {
+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;
+ stbi__uint16* enlarged;
- enlarged = (stbi__uint16 *)stbi__malloc(img_len * 2);
+ enlarged = (stbi__uint16*)stbi__malloc(img_len * 2);
if (enlarged == NULL)
- return (stbi__uint16 *)stbi__errpuc("outofmem", "Out of memory");
+ return (stbi__uint16*)stbi__errpuc("outofmem", "Out of memory");
for (i = 0; i < img_len; ++i)
enlarged[i] =
return enlarged;
}
-static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) {
+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;
+ 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;
+ 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) {
}
}
-static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) {
+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;
+ 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) {
+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);
+ void* result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);
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);
+ result = stbi__convert_16_to_8((stbi__uint16*)result, *x, *y, req_comp == 0 ? *comp : req_comp);
ri.bits_per_channel = 8;
}
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) {
+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);
+ void* result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16);
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);
+ result = stbi__convert_8_to_16((stbi_uc*)result, *x, *y, req_comp == 0 ? *comp : req_comp);
ri.bits_per_channel = 16;
}
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) {
+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));
#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;
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;
+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);
return result;
}
-STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) {
- unsigned char *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);
return result;
}
-STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) {
- stbi__uint16 *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);
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;
+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");
+ 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
-STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file,
+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) {
+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);
+ 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) {
+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,
+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);
+ 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;
+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);
+ 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);
}
#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;
+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);
+ 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;
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) {
+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,
+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);
+ 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");
+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);
return result;
}
-STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int 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);
// 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) {
+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);
}
#ifndef STBI_NO_STDIO
-STBIDEF int stbi_is_hdr(char const *filename) {
- FILE *f = stbi__fopen(filename, "rb");
+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);
return result;
}
-STBIDEF int stbi_is_hdr_from_file(FILE *f) {
+STBIDEF int stbi_is_hdr_from_file(FILE* f) {
#ifndef STBI_NO_HDR
long pos = ftell(f);
int res;
}
#endif // !STBI_NO_STDIO
-STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) {
+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);
+ stbi__start_callbacks(&s, (stbi_io_callbacks*)clbk, user);
return stbi__hdr_test(&s);
#else
STBI_NOTUSED(clbk);
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);
+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
}
}
-stbi_inline static stbi_uc stbi__get8(stbi__context *s) {
+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) {
return 0;
}
-stbi_inline static int stbi__at_eof(stbi__context *s) {
+stbi_inline static int stbi__at_eof(stbi__context* s) {
if (s->io.read) {
if (!(s->io.eof)(s->io_user_data))
return 0;
return s->img_buffer >= s->img_buffer_end;
}
-static void stbi__skip(stbi__context *s, int n) {
+static void stbi__skip(stbi__context* s, int n) {
if (n < 0) {
s->img_buffer = s->img_buffer_end;
return;
s->img_buffer += n;
}
-static int stbi__getn(stbi__context *s, stbi_uc *buffer, int 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) {
memcpy(buffer, s->img_buffer, blen);
- count = (s->io.read)(s->io_user_data, (char *)buffer + blen, n - 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;
return 0;
}
-static int stbi__get16be(stbi__context *s) {
+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) {
+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) {
+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) {
+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
//////////////////////////////////////////////////////////////////////////////
//
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,
+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;
+ 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);
+ 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;
+ 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__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)
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,
+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;
+ 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);
+ 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");
+ 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;
+ 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__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)
}
#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) {
int i, k, n;
- float *output;
+ float* output;
if (!data)
return NULL;
- output = (float *)stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
+ output = (float*)stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
if (output == NULL) {
STBI_FREE(data);
return stbi__errpf("outofmem", "Out of memory");
#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) {
+static stbi_uc* stbi__hdr_to_ldr(float* data, int x, int y, int comp) {
int i, k, n;
- stbi_uc *output;
+ stbi_uc* output;
if (!data)
return NULL;
- output = (stbi_uc *)stbi__malloc_mad3(x, y, comp, 0);
+ output = (stbi_uc*)stbi__malloc_mad3(x, y, comp, 0);
if (output == NULL) {
STBI_FREE(data);
return stbi__errpuc("outofmem", "Out of memory");
} stbi__huffman;
typedef struct {
- stbi__context *s;
+ stbi__context* s;
stbi__huffman huff_dc[4];
stbi__huffman huff_ac[4];
stbi__uint16 dequant[4][64];
int dc_pred;
int x, y, w2, h2;
- stbi_uc *data;
- void *raw_data, *raw_coeff;
- stbi_uc *linebuf;
- short *coeff; // progressive only
+ 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];
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,
+ 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_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) {
+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)
// 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) {
+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];
}
}
-static void stbi__grow_buffer_unsafe(stbi__jpeg *j) {
+static void stbi__grow_buffer_unsafe(stbi__jpeg* j) {
do {
unsigned int b = j->nomore ? 0 : stbi__get8(j->s);
if (b == 0xff) {
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) {
+stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg* j, stbi__huffman* h) {
unsigned int temp;
int c, k;
// 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) {
+stbi_inline static int stbi__extend_receive(stbi__jpeg* j, int n) {
unsigned int k;
int sgn;
if (j->code_bits < n)
}
// get some unsigned bits
-stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) {
+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);
return k;
}
-stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) {
+stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg* j) {
unsigned int k;
if (j->code_bits < 1)
stbi__grow_buffer_unsafe(j);
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) {
+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;
return 1;
}
-static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) {
+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)
// @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) {
+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->eob_run) {
--j->eob_run;
for (k = j->spec_start; k <= j->spec_end; ++k) {
- short *p = &data[stbi__jpeg_dezigzag[k]];
+ short* p = &data[stbi__jpeg_dezigzag[k]];
if (*p != 0)
if (stbi__jpeg_get_bit(j))
if ((*p & bit) == 0) {
// advance by r
while (k <= j->spec_end) {
- short *p = &data[stbi__jpeg_dezigzag[k++]];
+ short* p = &data[stbi__jpeg_dezigzag[k++]];
if (*p != 0) {
if (stbi__jpeg_get_bit(j))
if ((*p & bit) == 0) {
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) \
t1 += p2 + p4; \
t0 += p1 + p3;
-static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) {
+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;
+ stbi_uc* o;
+ short* d = data;
// columns
for (i = 0; i < 8; ++i, ++d, ++v) {
// 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]) {
+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;
__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));
+ 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);
dct_interleave8(p1, p3); // a4b4c4d4...
// store
- _mm_storel_epi64((__m128i *)out, p0);
+ _mm_storel_epi64((__m128i*)out, p0);
out += out_stride;
- _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p0, 0x4e));
+ _mm_storel_epi64((__m128i*)out, _mm_shuffle_epi32(p0, 0x4e));
out += out_stride;
- _mm_storel_epi64((__m128i *)out, p2);
+ _mm_storel_epi64((__m128i*)out, p2);
out += out_stride;
- _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p2, 0x4e));
+ _mm_storel_epi64((__m128i*)out, _mm_shuffle_epi32(p2, 0x4e));
out += out_stride;
- _mm_storel_epi64((__m128i *)out, p1);
+ _mm_storel_epi64((__m128i*)out, p1);
out += out_stride;
- _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p1, 0x4e));
+ _mm_storel_epi64((__m128i*)out, _mm_shuffle_epi32(p1, 0x4e));
out += out_stride;
- _mm_storel_epi64((__m128i *)out, p3);
+ _mm_storel_epi64((__m128i*)out, p3);
out += out_stride;
- _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p3, 0x4e));
+ _mm_storel_epi64((__m128i*)out, _mm_shuffle_epi32(p3, 0x4e));
}
#undef dct_const
// 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]) {
+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));
// 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) {
+static stbi_uc stbi__get_marker(stbi__jpeg* j) {
stbi_uc x;
if (j->marker != STBI__MARKER_none) {
x = j->marker;
// after a restart interval, stbi__jpeg_reset the entropy decoder and
// the dc prediction
-static void stbi__jpeg_reset(stbi__jpeg *j) {
+static void stbi__jpeg_reset(stbi__jpeg* j) {
j->code_bits = 0;
j->code_buffer = 0;
j->nomore = 0;
// since we don't even allow 1<<30 pixels
}
-static int stbi__parse_entropy_coded_data(stbi__jpeg *z) {
+static int stbi__parse_entropy_coded_data(stbi__jpeg* z) {
stbi__jpeg_reset(z);
if (!z->progressive) {
if (z->scan_n == 1) {
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);
+ 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;
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);
+ 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;
}
}
}
-static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) {
+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) {
+static void stbi__jpeg_finish(stbi__jpeg* z) {
if (z->progressive) {
// dequantize and idct the data
int i, j, n;
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);
+ 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) {
+static int stbi__process_marker(stbi__jpeg* z, int m) {
int L;
switch (m) {
case STBI__MARKER_none: // no marker found
case 0xC4: // DHT - define huffman table
L = stbi__get16be(z->s) - 2;
while (L > 0) {
- stbi_uc *v;
+ stbi_uc* v;
int sizes[16], i, n = 0;
int q = stbi__get8(z->s);
int tc = q >> 4;
}
// after we see SOS
-static int stbi__process_scan_header(stbi__jpeg *z) {
+static int stbi__process_scan_header(stbi__jpeg* z) {
int i;
int Ls = stbi__get16be(z->s);
z->scan_n = stbi__get8(z->s);
return 1;
}
-static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) {
+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) {
return why;
}
-static int stbi__process_frame_header(stbi__jpeg *z, int scan) {
- stbi__context *s = z->s;
+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)
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);
+ 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].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);
+ z->img_comp[i].coeff = (short*)(((size_t)z->img_comp[i].raw_coeff + 15) & ~15);
}
}
#define stbi__SOF_progressive(x) ((x) == 0xc2)
-static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) {
+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
}
// decode image to YCbCr format
-static int stbi__decode_jpeg_image(stbi__jpeg *j) {
+static int stbi__decode_jpeg_image(stbi__jpeg* j) {
int m;
for (m = 0; m < 4; m++) {
j->img_comp[m].raw_data = NULL;
// 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))
-static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) {
+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);
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) {
+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);
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) {
+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;
+ stbi_uc* input = in_near;
if (w == 1) {
// if only one sample, can't do any interpolation
#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) {
+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) {
}
#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) {
+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;
// 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 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);
// pack and write output
__m128i outv = _mm_packus_epi16(de0, de1);
- _mm_storeu_si128((__m128i *)(out + i * 2), outv);
+ _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)
}
#endif
-static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) {
+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);
// 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,
+#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) {
}
#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,
+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;
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 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
__m128i o1 = _mm_unpackhi_epi16(t0, t1);
// store
- _mm_storeu_si128((__m128i *)(out + 0), o0);
- _mm_storeu_si128((__m128i *)(out + 16), o1);
+ _mm_storeu_si128((__m128i*)(out + 0), o0);
+ _mm_storeu_si128((__m128i*)(out + 16), o1);
out += 32;
}
}
#endif
// set up the kernels
-static void stbi__setup_jpeg(stbi__jpeg *j) {
+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;
}
// clean up the temporary component buffers
-static void stbi__cleanup_jpeg(stbi__jpeg *j) { stbi__free_jpeg_components(j, j->s->img_n, 0); }
+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;
+ 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
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) {
+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
{
int k;
unsigned int i, j;
- stbi_uc *output;
- stbi_uc *coutput[4];
+ 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];
+ 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);
+ 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");
}
// 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);
+ 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;
+ stbi_uc* out = output + n * z->s->img_x * j;
for (k = 0; k < decode_n; ++k) {
- stbi__resample *r = &res_comp[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 (n >= 3) {
- stbi_uc *y = coutput[0];
+ stbi_uc* y = coutput[0];
if (z->s->img_n == 3) {
if (is_rgb) {
for (i = 0; i < z->s->img_x; ++i) {
out += n;
}
} else {
- stbi_uc *y = coutput[0];
+ stbi_uc* y = coutput[0];
if (n == 1)
for (i = 0; i < z->s->img_x; ++i)
out[i] = y[i];
}
}
-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));
+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);
return result;
}
-static int stbi__jpeg_test(stbi__context *s) {
+static int stbi__jpeg_test(stbi__context* s) {
int r;
- stbi__jpeg *j = (stbi__jpeg *)stbi__malloc(sizeof(stbi__jpeg));
+ 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);
return r;
}
-static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) {
+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;
return 1;
}
-static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) {
+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)));
+ 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 stbi__bitreverse16(v) >> (16 - bits);
}
-static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) {
+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];
// memory buffer
typedef struct {
- stbi_uc *zbuffer, *zbuffer_end;
+ stbi_uc * zbuffer, *zbuffer_end;
int num_bits;
stbi__uint32 code_buffer;
- char *zout;
- char *zout_start;
- char *zout_end;
+ char* zout;
+ char* zout_start;
+ char* zout_end;
int z_expandable;
stbi__zhuffman z_length, z_distance;
} stbi__zbuf;
-stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) {
+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) {
+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;
} while (z->num_bits <= 24);
}
-stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) {
+stbi_inline static unsigned int stbi__zreceive(stbi__zbuf* z, int n) {
unsigned int k;
if (z->num_bits < n)
stbi__fill_bits(z);
return k;
}
-static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) {
+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
return z->value[b];
}
-stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) {
+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);
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
+static int stbi__zexpand(stbi__zbuf* z, char* zout, int n) // need to make room for n bytes
{
- char *q;
+ char* q;
int cur, limit, old_limit;
z->zout = zout;
if (!z->z_expandable)
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);
+ 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");
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;
+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) {
}
*zout++ = (char)z;
} else {
- stbi_uc *p;
+ stbi_uc* p;
int len, dist;
if (z == 256) {
a->zout = zout;
return 0;
zout = a->zout;
}
- p = (stbi_uc *)(zout - dist);
+ p = (stbi_uc*)(zout - dist);
if (dist == 1) { // run of one byte; common in images.
stbi_uc v = *p;
if (len) {
}
}
-static int stbi__compute_huffman_codes(stbi__zbuf *a) {
+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
return 1;
}
-static int stbi__parse_uncompressed_block(stbi__zbuf *a) {
+static int stbi__parse_uncompressed_block(stbi__zbuf* a) {
stbi_uc header[4];
int len, nlen, k;
if (a->num_bits & 7)
return 1;
}
-static int stbi__parse_zlib_header(stbi__zbuf *a) {
+static int stbi__parse_zlib_header(stbi__zbuf* a) {
int cmf = stbi__zget8(a);
int cm = cmf & 15;
/* int cinfo = cmf >> 4; */
}
*/
-static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) {
+static int stbi__parse_zlib(stbi__zbuf* a, int parse_header) {
int final, type;
if (parse_header)
if (!stbi__parse_zlib_header(a))
return 1;
}
-static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) {
+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;
return stbi__parse_zlib(a, parse_header);
}
-STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) {
+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);
+ char* p = (char*)stbi__malloc(initial_size);
if (p == NULL)
return NULL;
- a.zbuffer = (stbi_uc *)buffer;
- a.zbuffer_end = (stbi_uc *)buffer + len;
+ 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);
}
}
-STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) {
+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,
+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);
+ char* p = (char*)stbi__malloc(initial_size);
if (p == NULL)
return NULL;
- a.zbuffer = (stbi_uc *)buffer;
- a.zbuffer_end = (stbi_uc *)buffer + len;
+ 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);
}
}
-STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) {
+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;
+ 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) {
+STBIDEF char* stbi_zlib_decode_noheader_malloc(char const* buffer, int len, int* outlen) {
stbi__zbuf a;
- char *p = (char *)stbi__malloc(16384);
+ char* p = (char*)stbi__malloc(16384);
if (p == NULL)
return NULL;
- a.zbuffer = (stbi_uc *)buffer;
- a.zbuffer_end = (stbi_uc *)buffer + len;
+ 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);
}
}
-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) {
stbi__zbuf a;
- a.zbuffer = (stbi_uc *)ibuffer;
- a.zbuffer_end = (stbi_uc *)ibuffer + ilen;
+ 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
stbi__uint32 type;
} stbi__pngchunk;
-static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) {
+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 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)
}
typedef struct {
- stbi__context *s;
- stbi_uc *idata, *expanded, *out;
+ stbi__context* s;
+ stbi_uc * idata, *expanded, *out;
int depth;
} stbi__png;
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,
+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__context* s = a->s;
stbi__uint32 i, j, stride = x * out_n * bytes;
stbi__uint32 img_len, img_width_bytes;
int k;
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
+ 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");
return stbi__err("not enough pixels", "Corrupt PNG");
for (j = 0; j < y; ++j) {
- stbi_uc *cur = a->out + stride * j;
- stbi_uc *prior;
+ stbi_uc* cur = a->out + stride * j;
+ stbi_uc* prior;
int filter = *raw++;
if (filter > 4)
// 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;
+ 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
// 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;
+ 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,
+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;
+ 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);
+ 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};
return 1;
}
-static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) {
- stbi__context *s = z->s;
+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;
+ stbi_uc* p = z->out;
// compute color-based transparency, assuming we've
// already got 255 as the alpha value in the output
return 1;
}
-static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) {
- stbi__context *s = z->s;
+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;
+ stbi__uint16* p = (stbi__uint16*)z->out;
// compute color-based transparency, assuming we've
// already got 65535 as the alpha value in the output
return 1;
}
-static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) {
+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;
+ stbi_uc * p, *temp_out, *orig = a->out;
- p = (stbi_uc *)stbi__malloc_mad2(pixel_count, pal_img_n, 0);
+ p = (stbi_uc*)stbi__malloc_mad2(pixel_count, pal_img_n, 0);
if (p == NULL)
return stbi__err("outofmem", "Out of memory");
stbi__de_iphone_flag = flag_true_if_should_convert;
}
-static void stbi__de_iphone(stbi__png *z) {
- stbi__context *s = z->s;
+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;
+ stbi_uc* p = z->out;
if (s->img_out_n == 3) { // convert bgr to rgb
for (i = 0; i < pixel_count; ++i) {
#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) {
+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;
+ stbi__context* s = z->s;
z->expanded = NULL;
z->idata = NULL;
return 0;
if (ioff + c.length > idata_limit) {
stbi__uint32 idata_limit_old = idata_limit;
- stbi_uc *p;
+ 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);
+ 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;
// 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);
+ 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);
}
}
-static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) {
- void *result = NULL;
+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 (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);
+ 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);
+ 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;
return result;
}
-static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) {
+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) {
+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) {
+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;
return 1;
}
-static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) {
+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) {
+static int stbi__png_is16(stbi__context* s) {
stbi__png p;
p.s = s;
if (!stbi__png_info_raw(&p, NULL, NULL, NULL))
// Microsoft/Windows BMP image
#ifndef STBI_NO_BMP
-static int stbi__bmp_test_raw(stbi__context *s) {
+static int stbi__bmp_test_raw(stbi__context* s) {
int r;
int sz;
if (stbi__get8(s) != 'B')
return r;
}
-static int stbi__bmp_test(stbi__context *s) {
+static int stbi__bmp_test(stbi__context* s) {
int r = stbi__bmp_test_raw(s);
stbi__rewind(s);
return r;
unsigned int mr, mg, mb, ma, all_a;
} stbi__bmp_data;
-static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) {
+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");
}
}
}
- return (void *)1;
+ 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;
+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;
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);
+ 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) {
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;
+ 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;
}
// 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) {
+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;
}
}
-static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) {
+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
return 1; // seems to have passed everything
}
-static int stbi__tga_test(stbi__context *s) {
+static int stbi__tga_test(stbi__context* s) {
int res = 0;
int sz, tga_color_type;
stbi__get8(s); // discard Offset
}
// read 16bit value and convert to 24bit RGB
-static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc *out) {
+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
// 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) {
+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_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;
+ unsigned char* tga_data;
+ unsigned char* tga_palette = NULL;
int i, j;
unsigned char raw_data[4] = {0};
int RLE_count = 0;
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);
+ tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);
if (!tga_data)
return stbi__errpuc("outofmem", "Out of memory");
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_uc* tga_row = tga_data + row * tga_width * tga_comp;
stbi__getn(s, tga_row, tga_width * tga_comp);
}
} else {
// 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);
+ 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_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);
// 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;
+ 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];
// 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) {
+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) {
+static int stbi__psd_decode_rle(stbi__context* s, stbi_uc* p, int pixelCount) {
int count, nleft, len;
count = 0;
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) {
+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_uc* out;
STBI_NOTUSED(ri);
// Check identifier
// Create the destination image.
if (!compression && bitdepth == 16 && bpc == 16) {
- out = (stbi_uc *)stbi__malloc_mad3(8, w, h, 0);
+ out = (stbi_uc*)stbi__malloc_mad3(8, w, h, 0);
ri->bits_per_channel = 16;
} else
- out = (stbi_uc *)stbi__malloc(4 * w * h);
+ out = (stbi_uc*)stbi__malloc(4 * w * h);
if (!out)
return stbi__errpuc("outofmem", "Out of memory");
// Read the RLE data by channel.
for (channel = 0; channel < 4; channel++) {
- stbi_uc *p;
+ stbi_uc* p;
p = out + channel;
if (channel >= channelCount) {
if (channel >= channelCount) {
// Fill this channel with default data.
if (bitdepth == 16 && bpc == 16) {
- stbi__uint16 *q = ((stbi__uint16 *)out) + channel;
+ 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* 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;
+ 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;
+ 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);
if (channelCount >= 4) {
if (ri->bits_per_channel == 16) {
for (i = 0; i < w * h; ++i) {
- stbi__uint16 *pixel = (stbi__uint16 *)out + 4 * 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;
}
} else {
for (i = 0; i < w * h; ++i) {
- unsigned char *pixel = out + 4 * 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;
// 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);
+ 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)
// 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) {
+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 1;
}
-static int stbi__pic_test_core(stbi__context *s) {
+static int stbi__pic_test_core(stbi__context* s) {
int i;
if (!stbi__pic_is4(s, "\x53\x80\xF6\x34"))
stbi_uc size, type, channel;
} stbi__pic_packet;
-static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) {
+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) {
return dest;
}
-static void stbi__copyval(int channel, stbi_uc *dest, const stbi_uc *src) {
+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)
dest[i] = src[i];
}
-static stbi_uc *stbi__pic_load_core(stbi__context *s, int width, int height, int *comp, stbi_uc *result) {
+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;
+ stbi__pic_packet* packet;
if (num_packets == sizeof(packets) / sizeof(packets[0]))
return stbi__errpuc("bad format", "too many packets");
int packet_idx;
for (packet_idx = 0; packet_idx < num_packets; ++packet_idx) {
- stbi__pic_packet *packet = &packets[packet_idx];
- stbi_uc *dest = result + y * width * 4;
+ stbi__pic_packet* packet = &packets[packet_idx];
+ stbi_uc* dest = result + y * width * 4;
switch (packet->type) {
default:
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;
+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);
stbi__get16be(s); // skip `pad'
// intermediate buffer is RGBA
- result = (stbi_uc *)stbi__malloc_mad3(x, y, 4, 0);
+ 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)) {
return result;
}
-static int stbi__pic_test(stbi__context *s) {
+static int stbi__pic_test(stbi__context* s) {
int r = stbi__pic_test_core(s);
stbi__rewind(s);
return r;
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;
+ 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;
+ stbi_uc* color_table;
int parse, step;
int lflags;
int start_x, start_y;
int delay;
} stbi__gif;
-static int stbi__gif_test_raw(stbi__context *s) {
+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;
return 1;
}
-static int stbi__gif_test(stbi__context *s) {
+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) {
+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);
}
}
-static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) {
+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");
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));
+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 1;
}
-static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) {
+static void stbi__out_gif_code(stbi__gif* g, stbi__uint16 code) {
stbi_uc *p, *c;
int idx;
}
}
-static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) {
+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;
+ stbi__gif_lzw* p;
lzw_cs = stbi__get8(s);
if (lzw_cs > 12)
// 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) {
+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;
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);
+ 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");
case 0x2C: /* Image Descriptor */
{
stbi__int32 x, y, w, h;
- stbi_uc *o;
+ stbi_uc* o;
x = stbi__get16le(s);
y = stbi__get16le(s);
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;
+ g->color_table = (stbi_uc*)g->lpal;
} else if (g->flags & 0x80) {
- g->color_table = (stbi_uc *)g->pal;
+ g->color_table = (stbi_uc*)g->pal;
} else
return stbi__errpuc("missing color table", "Corrupt GIF");
break;
}
- case 0x3B: // gif stream termination code
- return (stbi_uc *)s; // using '1' causes warning on some compilers
+ 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) {
+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_uc* u = 0;
+ stbi_uc* out = 0;
+ stbi_uc* two_back = 0;
stbi__gif g;
int stride;
memset(&g, 0, sizeof(g));
do {
u = stbi__gif_load_next(s, &g, comp, req_comp, two_back);
- if (u == (stbi_uc *)s)
+ if (u == (stbi_uc*)s)
u = 0; // end of animated gif marker
if (u) {
stride = g.w * g.h * 4;
if (out) {
- out = (stbi_uc *)STBI_REALLOC(out, layers * stride);
+ out = (stbi_uc*)STBI_REALLOC(out, layers * stride);
if (delays) {
- *delays = (int *)STBI_REALLOC(*delays, sizeof(int) * layers);
+ *delays = (int*)STBI_REALLOC(*delays, sizeof(int) * layers);
}
} else {
- out = (stbi_uc *)stbi__malloc(layers * stride);
+ out = (stbi_uc*)stbi__malloc(layers * stride);
if (delays) {
- *delays = (int *)stbi__malloc(layers * sizeof(int));
+ *delays = (int*)stbi__malloc(layers * sizeof(int));
}
}
memcpy(out + ((layers - 1) * stride), u, stride);
}
}
-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;
+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)
+ if (u == (stbi_uc*)s)
u = 0; // end of animated gif marker
if (u) {
*x = g.w;
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 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) {
+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 1;
}
-static int stbi__hdr_test(stbi__context *s) {
+static int stbi__hdr_test(stbi__context* s) {
int r = stbi__hdr_test_core(s, "#?RADIANCE\n");
stbi__rewind(s);
if (!r) {
}
#define STBI__HDR_BUFLEN 1024
-static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) {
+static char* stbi__hdr_gettoken(stbi__context* z, char* buffer) {
int len = 0;
char c = '\0';
return buffer;
}
-static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) {
+static void stbi__hdr_convert(float* output, stbi_uc* input, int req_comp) {
if (input[3] != 0) {
float f1;
// Exponent
}
}
-static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) {
+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;
+ char* token;
int valid = 0;
int width, height;
- stbi_uc *scanline;
- float *hdr_data;
+ stbi_uc* scanline;
+ float* hdr_data;
int len;
unsigned char count, value;
int i, j, k, c1, c2, z;
- const char *headerToken;
+ const char* headerToken;
STBI_NOTUSED(ri);
// Check identifier
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);
+ hdr_data = (float*)stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);
if (!hdr_data)
return stbi__errpf("outofmem", "Out of memory");
return stbi__errpf("invalid decoded scanline length", "corrupt HDR");
}
if (scanline == NULL) {
- scanline = (stbi_uc *)stbi__malloc_mad2(width, 4, 0);
+ scanline = (stbi_uc*)stbi__malloc_mad2(width, 4, 0);
if (!scanline) {
STBI_FREE(hdr_data);
return stbi__errpf("outofmem", "Out of memory");
return hdr_data;
}
-static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) {
+static int stbi__hdr_info(stbi__context* s, int* x, int* y, int* comp) {
char buffer[STBI__HDR_BUFLEN];
- char *token;
+ char* token;
int valid = 0;
int dummy;
#endif // STBI_NO_HDR
#ifndef STBI_NO_BMP
-static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) {
- void *p;
+static int stbi__bmp_info(stbi__context* s, int* x, int* y, int* comp) {
+ void* p;
stbi__bmp_data info;
info.all_a = 255;
#endif
#ifndef STBI_NO_PSD
-static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) {
+static int stbi__psd_info(stbi__context* s, int* x, int* y, int* comp) {
int channelCount, dummy, depth;
if (!x)
x = &dummy;
return 1;
}
-static int stbi__psd_is16(stbi__context *s) {
+static int stbi__psd_is16(stbi__context* s) {
int channelCount, depth;
if (stbi__get32be(s) != 0x38425053) {
stbi__rewind(s);
#endif
#ifndef STBI_NO_PIC
-static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) {
+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];
stbi__skip(s, 8);
do {
- stbi__pic_packet *packet;
+ stbi__pic_packet* packet;
if (num_packets == sizeof(packets) / sizeof(packets[0]))
return 0;
#ifndef STBI_NO_PNM
-static int stbi__pnm_test(stbi__context *s) {
+static int stbi__pnm_test(stbi__context* s) {
char p, t;
p = (char)stbi__get8(s);
t = (char)stbi__get8(s);
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;
+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))
+ if (!stbi__pnm_info(s, (int*)&s->img_x, (int*)&s->img_y, (int*)&s->img_n))
return 0;
*x = s->img_x;
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);
+ 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);
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
}
-static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) {
+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 int stbi__pnm_isdigit(char c) { return c >= '0' && c <= '9'; }
-static int stbi__pnm_getinteger(stbi__context *s, char *c) {
+static int stbi__pnm_getinteger(stbi__context* s, char* c) {
int value = 0;
while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
return value;
}
-static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) {
+static int stbi__pnm_info(stbi__context* s, int* x, int* y, int* comp) {
int maxv, dummy;
char c, p, t;
}
#endif
-static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) {
+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;
return stbi__err("unknown image type", "Image not of any known type, or corrupt");
}
-static int stbi__is_16_main(stbi__context *s) {
+static int stbi__is_16_main(stbi__context* s) {
#ifndef STBI_NO_PNG
if (stbi__png_is16(s))
return 1;
}
#ifndef STBI_NO_STDIO
-STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) {
- FILE *f = stbi__fopen(filename, "rb");
+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");
return result;
}
-STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) {
+STBIDEF int stbi_info_from_file(FILE* f, int* x, int* y, int* comp) {
int r;
stbi__context s;
long pos = ftell(f);
return r;
}
-STBIDEF int stbi_is_16_bit(char const *filename) {
- FILE *f = stbi__fopen(filename, "rb");
+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");
return result;
}
-STBIDEF int stbi_is_16_bit_from_file(FILE *f) {
+STBIDEF int stbi_is_16_bit_from_file(FILE* f) {
int r;
stbi__context s;
long pos = ftell(f);
}
#endif // !STBI_NO_STDIO
-STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *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) {
+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);
+ 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) {
+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) {
+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);
+ stbi__start_callbacks(&s, (stbi_io_callbacks*)c, user);
return stbi__is_16_main(&s);
}
#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_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_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);
#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);
+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,
+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,
+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 void stbi_flip_vertically_on_write(int flip_boolean);
#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;
STBIWDEF void stbi_flip_vertically_on_write(int flag) { stbi__flip_vertically_on_write = flag; }
typedef struct {
- stbi_write_func *func;
- void *context;
+ 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) {
+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 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);
+ 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) {
+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];
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);
+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) {
+static void stbiw__writefv(stbi__write_context* s, const char* fmt, va_list v) {
while (*fmt) {
switch (*fmt++) {
case ' ':
}
}
-static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) {
+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) {
+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;
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) {
+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;
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,
+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;
for (; j != j_end; j += vdir) {
for (i = 0; i < x; ++i) {
- unsigned char *d = (unsigned char *)data + (j * x + i) * comp;
+ 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, ...) {
+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 {
}
}
-static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) {
+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,
+ 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) {
+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) {
+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);
}
#endif //! STBI_WRITE_NO_STDIO
-static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) {
+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
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,
+ 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;
jdir = -1;
}
for (; j != jend; j += jdir) {
- unsigned char *row = (unsigned char *)data + j * x * comp;
+ unsigned char* row = (unsigned char*)data + j * x * comp;
int len;
for (i = 0; i < x; i += len) {
- unsigned char *begin = row + i * comp;
+ unsigned char* begin = row + i * comp;
int diff = 1;
len = 1;
++len;
diff = memcmp(begin, row + (i + 1) * comp, comp);
if (diff) {
- const unsigned char *prev = begin;
+ const unsigned char* prev = begin;
for (k = i + 2; k < x && len < 128; ++k) {
if (memcmp(prev, row + k * comp, comp)) {
prev += comp;
return 1;
}
-STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const 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);
+ 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) {
+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);
+ int r = stbi_write_tga_core(&s, x, y, comp, (void*)data);
stbi__end_write_file(&s);
return r;
} else
#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
-static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) {
+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__write_run_data(stbi__write_context *s, int length, unsigned char databyte) {
+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) {
+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) {
+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];
/* RLE each component separately */
for (c = 0; c < 4; c++) {
- unsigned char *comp = &scratch[width * c];
+ unsigned char* comp = &scratch[width * c];
x = 0;
while (x < width) {
}
}
-static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) {
+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);
+ 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";
}
}
-STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const 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);
+ 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) {
+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);
+ int r = stbi_write_hdr_core(&s, x, y, comp, (float*)data);
stbi__end_write_file(&s);
return r;
} else
#ifndef STBIW_ZLIB_COMPRESS
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
-#define stbiw__sbraw(a) ((int *)(a)-2)
+#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__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__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) {
+static void* stbiw__sbgrowf(void** arr, int increment, int itemsize) {
int m = *arr ? 2 * stbiw__sbm(*arr) + increment : increment + 1;
- void *p =
+ 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);
+ ((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) {
+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;
return res;
}
-static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) {
+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])
return i;
}
-static unsigned int stbiw__zhash(unsigned char *data) {
+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;
#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_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) \
#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);
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 **));
+ 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)
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];
+ 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
*out_len = stbiw__sbn(out);
// make returned pointer freeable
STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
- return (unsigned char *)stbiw__sbraw(out);
+ 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
#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) {
+static void stbiw__wpcrc(unsigned char** data, int len) {
unsigned int crc = stbiw__crc32(*data - len - 4, len + 4);
stbiw__wp32(*data, crc);
}
}
// @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 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* 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);
+ 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) {
}
}
-STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n,
- int *out_len) {
+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;
+ signed char* line_buffer;
int j, zlen;
if (stride_bytes == 0)
force_filter = -1;
}
- filt = (unsigned char *)STBIW_MALLOC((x * n + 1) * y);
+ filt = (unsigned char*)STBIW_MALLOC((x * n + 1) * y);
if (!filt)
return 0;
- line_buffer = (signed char *)STBIW_MALLOC(x * n);
+ line_buffer = (signed char*)STBIW_MALLOC(x * n);
if (!line_buffer) {
STBIW_FREE(filt);
return 0;
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);
+ 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);
+ 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;
}
}
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);
+ stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
filter_type = best_filter;
}
}
return 0;
// each tag requires 12 bytes of overhead
- out = (unsigned char *)STBIW_MALLOC(8 + 12 + 13 + 12 + zlen + 12);
+ out = (unsigned char*)STBIW_MALLOC(8 + 12 + 13 + 12 + zlen + 12);
if (!out)
return 0;
*out_len = 8 + 12 + 13 + 12 + zlen + 12;
}
#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;
+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);
+ unsigned char* png = stbi_write_png_to_mem((const unsigned char*)data, stride_bytes, x, y, comp, &len);
if (png == NULL)
return 0;
}
#endif
-STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data,
+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);
+ 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);
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) {
+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);
*bitCntP = bitCnt;
}
-static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p,
- float *d7p) {
+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;
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,
+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]};
return DU[0];
}
-static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void *data, int quality) {
+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};
0x01,
0xA2,
0};
- s->func(s->context, (void *)head0, sizeof(head0));
- s->func(s->context, (void *)YTable, sizeof(YTable));
+ 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));
+ 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));
+ 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));
+ 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));
+ 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;
+ 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)
return 1;
}
-STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *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) {
stbi__write_context s;
stbi__start_write_callbacks(&s, func, context);
- return stbi_write_jpg_core(&s, x, y, comp, (void *)data, quality);
+ 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) {
+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);
// private structure
typedef struct {
- unsigned char *data;
+ unsigned char* data;
int cursor;
int size;
} stbtt__buf;
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)
+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
+ 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_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
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
+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
+ 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.
//////////////////////////////////////////////////////////////////////////////
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))
-STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index,
+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_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
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* array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints
int num_chars;
- stbtt_packedchar *chardata_for_range; // output
+ 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
// times within a single PackBegin/PackEnd.
-STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
+STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context* spc, unsigned int h_oversample, unsigned int v_oversample);
// Oversampling a font increases the quality by allowing higher-quality subpixel
// positioning, and is especially valuable at smaller text sizes.
//
// To use with PackFontRangesGather etc., you must set it before calls
// call to PackFontRangesGatherRects.
-STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
+STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context* spc, int skip);
// If skip != 0, this tells stb_truetype to skip any codepoints for which
// there is no corresponding glyph. If skip=0, which is the default, then
// codepoints without a glyph recived the font's "missing character" glyph,
// typically an empty box by convention.
-STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
+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
+ float* xpos, float* ypos, // pointers to current position in screen pixel space
+ stbtt_aligned_quad* q, // output: quad to draw
int align_to_integer);
-STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info,
- stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
-STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
-STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info,
- stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
+STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context* spc, const stbtt_fontinfo* info,
+ stbtt_pack_range* ranges, int num_ranges, stbrp_rect* rects);
+STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context* spc, stbrp_rect* rects, int num_rects);
+STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context* spc, const stbtt_fontinfo* info,
+ stbtt_pack_range* ranges, int num_ranges, stbrp_rect* rects);
// Calling these functions in sequence is roughly equivalent to calling
// stbtt_PackFontRanges(). If you more control over the packing of multiple
// fonts, or if you want to pack custom data into a font texture, take a look
// 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;
+ 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;
+ unsigned char* pixels;
+ void* nodes;
};
//////////////////////////////////////////////////////////////////////////////
//
//
-STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
+STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char* data);
// This function will determine the number of fonts in a font file. TrueType
// collection (.ttc) files may contain multiple fonts, while TrueType font
// (.ttf) files only contain one font. The number of fonts can be used for
// indexing with the previous function where the index is between zero and one
// less than the total fonts. If an error occurs, -1 is returned.
-STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
+STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char* data, int index);
// Each .ttf/.ttc file may have more than one font. Each font has a sequential
// index number starting from 0. Call this function to get the font offset for
// a given index; it returns -1 if the index is out of range. A regular .ttf
// 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
+ 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
stbtt__buf fdselect; // map from glyph to fontdict
};
-STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
+STBTT_DEF int stbtt_InitFont(stbtt_fontinfo* info, const unsigned char* data, int offset);
// Given an offset into the file that defines a font, this function builds
// the necessary cached info for the rest of the system. You must allocate
// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
//
// CHARACTER TO GLYPH-INDEX CONVERSIOn
-STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
+STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo* info, int unicode_codepoint);
// If you're going to perform multiple operations on the same character
// and you want a speed-up, call this function with the character you're
// going to process, then use glyph-based functions instead of the
// CHARACTER PROPERTIES
//
-STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
+STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo* info, float pixels);
// computes a scale factor to produce a font whose "height" is 'pixels' tall.
// Height is measured as the distance from the highest ascender to the lowest
// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
// scale = pixels / (ascent - descent)
// so if you prefer to measure height by the ascent only, use a similar calculation.
-STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
+STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo* info, float pixels);
// computes a scale factor to produce a font whose EM size is mapped to
// 'pixels' tall. This is probably what traditional APIs compute, but
// I'm not positive.
-STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
+STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo* info, int* ascent, int* descent, int* lineGap);
// ascent is the coordinate above the baseline the font extends; descent
// is the coordinate below the baseline the font extends (i.e. it is typically negative)
// lineGap is the spacing between one row's descent and the next row's ascent...
// 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).
//
// Returns 1 on success (table present), 0 on failure.
-STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
+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);
+STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo* info, int codepoint, int* x0, int* y0, int* x1, int* y1);
// Gets the bounding box of the visible part of the glyph, in unscaled coordinates
-STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth,
- int *leftSideBearing);
-STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
-STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
+STBTT_DEF void stbtt_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 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)
} stbtt_vertex;
#endif
-STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
+STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo* info, int glyph_index);
// returns non-zero if nothing is drawn for this glyph
-STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
-STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
+STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo* info, int unicode_codepoint, stbtt_vertex** vertices);
+STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo* info, int glyph_index, stbtt_vertex** vertices);
// returns # of vertices and fills *vertices with the pointer to them
// these are expressed in "unscaled" coordinates
//
// draws a quadratic bezier from previous endpoint to
// its x,y, using cx,cy as the bezier control point.
-STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
+STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo* info, stbtt_vertex* vertices);
// 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 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);
// fills svg with the character's SVG data.
// returns data size or 0 if SVG not found.
// BITMAP RENDERING
//
-STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
+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,
+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,
+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,
+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);
+ 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,
+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,
+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,
+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);
+ 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;
+ 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
+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
+ 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
+ void* userdata); // context for to STBTT_MALLOC
//////////////////////////////////////////////////////////////////////////////
//
// Signed Distance Function (or Field) rendering
-STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
+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.
// 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);
+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
#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);
+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,
+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.
// stbtt__buf helpers to parse data from file
//
-static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) {
+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) {
+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) {
+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) {
+static stbtt_uint32 stbtt__buf_get(stbtt__buf* b, int n) {
stbtt_uint32 v = 0;
int i;
STBTT_assert(n >= 1 && n <= 4);
return v;
}
-static stbtt__buf stbtt__new_buf(const void *p, size_t size) {
+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.data = (stbtt_uint8*)p;
r.size = (int)size;
r.cursor = 0;
return r;
#define stbtt__buf_get16(b) stbtt__buf_get((b), 2)
#define stbtt__buf_get32(b) stbtt__buf_get((b), 4)
-static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) {
+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;
return r;
}
-static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) {
+static stbtt__buf stbtt__cff_get_index(stbtt__buf* b) {
int count, start, offsize;
start = b->cursor;
count = stbtt__buf_get16(b);
return stbtt__buf_range(b, start, b->cursor - start);
}
-static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) {
+static stbtt_uint32 stbtt__cff_int(stbtt__buf* b) {
int b0 = stbtt__buf_get8(b);
if (b0 >= 32 && b0 <= 246)
return b0 - 139;
return 0;
}
-static void stbtt__cff_skip_operand(stbtt__buf *b) {
+static void stbtt__cff_skip_operand(stbtt__buf* b) {
int v, b0 = stbtt__buf_peek8(b);
STBTT_assert(b0 >= 28);
if (b0 == 30) {
}
}
-static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) {
+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;
return stbtt__buf_range(b, 0, 0);
}
-static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) {
+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) {
+static int stbtt__cff_index_count(stbtt__buf* b) {
stbtt__buf_seek(b, 0);
return stbtt__buf_get16(b);
}
// 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 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]; }
+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) {
+static int stbtt__isfont(stbtt_uint8* font) {
// check the version number
if (stbtt_tag4(font, '1', 0, 0, 0))
return 1; // TrueType 1
}
// @OPTIMIZE: binary search
-static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) {
+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;
return 0;
}
-static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) {
+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;
return -1;
}
-static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) {
+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;
}
// since most people won't use this, find this table the first time it's needed
-static int stbtt__get_svg(stbtt_fontinfo *info) {
+static int stbtt__get_svg(stbtt_fontinfo* info) {
stbtt_uint32 t;
if (info->svg < 0) {
t = stbtt__find_table(info->data, info->fontstart, "SVG ");
return info->svg;
}
-static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) {
+static int stbtt_InitFont_internal(stbtt_fontinfo* info, unsigned char* data, int fontstart) {
stbtt_uint32 cmap, t;
stbtt_int32 i, numTables;
return 1;
}
-STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) {
- stbtt_uint8 *data = info->data;
+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);
return 0;
}
-STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **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,
+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->cy = (stbtt_int16)cy;
}
-static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) {
+static int stbtt__GetGlyfOffset(const stbtt_fontinfo* info, int glyph_index) {
int g1, g2;
STBTT_assert(!info->cff.size);
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);
+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) {
+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 {
return 1;
}
-STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) {
+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_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo* info, int glyph_index) {
stbtt_int16 numberOfContours;
int g;
if (info->cff.size)
return numberOfContours == 0;
}
-static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, stbtt_int32 sx,
+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)
return num_vertices;
}
-static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) {
+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;
+ stbtt_uint8* endPtsOfContours;
+ stbtt_uint8* data = info->data;
+ stbtt_vertex* vertices = 0;
int num_vertices = 0;
int g = stbtt__GetGlyfOffset(info, glyph_index);
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;
+ 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);
+ vertices = (stbtt_vertex*)STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
if (vertices == 0)
return 0;
} else if (numberOfContours < 0) {
// Compound shapes.
int more = 1;
- stbtt_uint8 *comp = data + g + 10;
+ stbtt_uint8* comp = data + g + 10;
num_vertices = 0;
vertices = 0;
while (more) {
if (comp_num_verts > 0) {
// Transform vertices.
for (i = 0; i < comp_num_verts; ++i) {
- stbtt_vertex *v = &comp_verts[i];
+ stbtt_vertex* v = &comp_verts[i];
stbtt_vertex_type x, y;
x = v->x;
y = v->y;
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);
+ tmp =
+ (stbtt_vertex*)STBTT_malloc((num_vertices + comp_num_verts) * sizeof(stbtt_vertex), info->userdata);
if (!tmp) {
if (vertices)
STBTT_free(vertices, info->userdata);
float x, y;
stbtt_int32 min_x, max_x, min_y, max_y;
- stbtt_vertex *pvertices;
+ 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 }
+#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) {
+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->started = 1;
}
-static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx,
+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);
c->num_vertices++;
}
-static void stbtt__csctx_close_shape(stbtt__csctx *ctx) {
+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) {
+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) {
+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,
+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;
return stbtt__cff_index_get(idx, n);
}
-static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) {
+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;
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) {
+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];
#undef STBTT__CSERR
}
-static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) {
+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);
+ *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 0;
}
-static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) {
+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)
return r ? c.num_vertices : 0;
}
-STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) {
+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_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)
}
}
-STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) {
- stbtt_uint8 *data = info->data + info->kern;
+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 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;
+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.
return length;
}
-static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) {
- stbtt_uint8 *data = info->data + info->kern;
+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;
return 0;
}
-static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) {
+static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8* coverageTable, int glyph) {
stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
switch (coverageFormat) {
case 1: {
stbtt_int32 l = 0, r = glyphCount - 1, m;
int straw, needle = glyph;
while (l <= r) {
- stbtt_uint8 *glyphArray = coverageTable + 4;
+ stbtt_uint8* glyphArray = coverageTable + 4;
stbtt_uint16 glyphID;
m = (l + r) >> 1;
glyphID = ttUSHORT(glyphArray + 2 * m);
case 2: {
stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
- stbtt_uint8 *rangeArray = coverageTable + 4;
+ 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;
+ stbtt_uint8* rangeRecord;
m = (l + r) >> 1;
rangeRecord = rangeArray + 6 * m;
strawStart = ttUSHORT(rangeRecord);
return -1;
}
-static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) {
+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;
+ stbtt_uint8* classDef1ValueArray = classDefTable + 6;
if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
case 2: {
stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
- stbtt_uint8 *classRangeRecords = classDefTable + 4;
+ stbtt_uint8* classRangeRecords = classDefTable + 4;
// Binary search.
stbtt_int32 l = 0, r = classRangeCount - 1, m;
int strawStart, strawEnd, needle = glyph;
while (l <= r) {
- stbtt_uint8 *classRangeRecord;
+ stbtt_uint8* classRangeRecord;
m = (l + r) >> 1;
classRangeRecord = classRangeRecords + 6 * m;
strawStart = ttUSHORT(classRangeRecord);
// 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) {
+static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo* info, int glyph1, int glyph2) {
stbtt_uint16 lookupListOffset;
- stbtt_uint8 *lookupList;
+ stbtt_uint8* lookupList;
stbtt_uint16 lookupCount;
- stbtt_uint8 *data;
+ stbtt_uint8* data;
stbtt_int32 i, sti;
if (!info->gpos)
for (i = 0; i < lookupCount; ++i) {
stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
- stbtt_uint8 *lookupTable = lookupList + lookupOffset;
+ stbtt_uint8* lookupTable = lookupList + lookupOffset;
stbtt_uint16 lookupType = ttUSHORT(lookupTable);
stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
- stbtt_uint8 *subTableOffsets = lookupTable + 6;
+ 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_uint8* table = lookupTable + subtableOffset;
stbtt_uint16 posFormat = ttUSHORT(table);
stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
stbtt_int32 valueRecordPairSizeInBytes = 2;
stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
- stbtt_uint8 *pairValueTable = table + pairPosOffset;
+ stbtt_uint8* pairValueTable = table + pairPosOffset;
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
- stbtt_uint8 *pairValueArray = pairValueTable + 2;
+ stbtt_uint8* pairValueArray = pairValueTable + 2;
if (coverageIndex >= pairSetCount)
return 0;
// Binary search.
while (l <= r) {
stbtt_uint16 secondGlyph;
- stbtt_uint8 *pairValue;
+ stbtt_uint8* pairValue;
m = (l + r) >> 1;
pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
secondGlyph = ttUSHORT(pairValue);
return 0;
}
-STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) {
+STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo* info, int g1, int g2) {
int xAdvance = 0;
if (info->gpos)
return xAdvance;
}
-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) {
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_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) {
+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)
*lineGap = ttSHORT(info->data + info->hhea + 8);
}
-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) {
int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
if (!tab)
return 0;
return 1;
}
-STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) {
+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) {
+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) {
+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) {
+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_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;
+ stbtt_uint8* svg_docs = svg_doc_list + 2;
for (i = 0; i < numEntries; i++) {
- stbtt_uint8 *svg_doc = svg_docs + (12 * 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;
+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);
+ *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) {
+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) {
+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
}
}
-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_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_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_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;
+ struct stbtt__hheap_chunk* next;
} stbtt__hheap_chunk;
typedef struct stbtt__hheap {
- struct stbtt__hheap_chunk *head;
- void *first_free;
+ 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) {
+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;
+ 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);
+ 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->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;
+ 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;
+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;
+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__hheap_chunk* n = c->next;
STBTT_free(c, userdata);
c = n;
}
} stbtt__edge;
typedef struct stbtt__active_edge {
- struct stbtt__active_edge *next;
+ struct stbtt__active_edge* next;
#if STBTT_RASTERIZER_VERSION == 1
int x, dx;
float ey;
#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);
+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;
}
#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);
+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);
// 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) {
+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;
}
}
-static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x,
- int off_y, void *userdata) {
+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;
+ 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);
+ scanline = (unsigned char*)STBTT_malloc(result->w, userdata);
else
scanline = scanline_data;
for (s = 0; s < vsubsample; ++s) {
// find center of pixel for this scanline
float scan_y = y + 0.5f;
- stbtt__active_edge **step = &active;
+ 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;
+ stbtt__active_edge* z = *step;
if (z->ey <= scan_y) {
*step = z->next; // delete from list
STBTT_assert(z->direction);
step = &active;
while (*step && (*step)->next) {
if ((*step)->x > (*step)->next->x) {
- stbtt__active_edge *t = *step;
- stbtt__active_edge *q = t->next;
+ stbtt__active_edge* t = *step;
+ stbtt__active_edge* q = t->next;
t->next = q->next;
q->next = t;
// 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);
+ 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 {
// find thing to insert AFTER
- stbtt__active_edge *p = active;
+ 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
// 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,
+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;
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,
+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;
}
// 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) {
+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;
+ 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);
+ scanline = (float*)STBTT_malloc((result->w * 2 + 1) * sizeof(float), userdata);
else
scanline = scanline_data;
// 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__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;
+ stbtt__active_edge* z = *step;
if (z->ey <= scan_y_top) {
*step = z->next; // delete from list
STBTT_assert(z->direction);
// 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);
+ 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) {
// advance all the edges
step = &active;
while (*step) {
- stbtt__active_edge *z = *step;
+ stbtt__active_edge* z = *step;
z->fx += z->fdx; // advance to position for current scanline
step = &((*step)->next); // advance through list
}
#define STBTT__COMPARE(a, b) ((a)->y0 < (b)->y0)
-static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) {
+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];
+ stbtt__edge* b = &p[j - 1];
int c = STBTT__COMPARE(a, b);
if (!c)
break;
}
}
-static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) {
+static void stbtt__sort_edges_quicksort(stbtt__edge* p, int n) {
/* threshold for transitioning to insertion sort */
while (n > 12) {
stbtt__edge t;
}
}
-static void stbtt__sort_edges(stbtt__edge *p, int n) {
+static void stbtt__sort_edges(stbtt__edge* p, int n) {
stbtt__sort_edges_quicksort(p, n);
stbtt__sort_edges_ins_sort(p, n);
}
float x, y;
} stbtt__point;
-static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x,
+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) {
+ void* userdata) {
float y_scale_inv = invert ? -scale_y : scale_y;
- stbtt__edge *e;
+ stbtt__edge* e;
int n, i, j, k, m;
#if STBTT_RASTERIZER_VERSION == 1
int vsubsample = result->h < 8 ? 15 : 5;
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
+ 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;
+ stbtt__point* p = pts + m;
m += wcount[i];
j = wcount[i] - 1;
for (k = 0; k < wcount[i]; j = k++) {
STBTT_free(e, userdata);
}
-static void stbtt__add_point(stbtt__point *points, int n, float x, float 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;
}
// 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,
+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;
return 1;
}
-static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1,
+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;
}
// 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;
+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;
if (n == 0)
return 0;
- *contour_lengths = (int *)STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
+ *contour_lengths = (int*)STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
if (*contour_lengths == 0) {
*num_contours = 0;
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);
+ points = (stbtt__point*)STBTT_malloc(num_points * sizeof(points[0]), userdata);
if (points == NULL)
goto error;
}
return NULL;
}
-STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts,
+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) {
+ 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,
+ 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,
}
}
-STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) { STBTT_free(bitmap, 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) {
+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;
+ stbtt_vertex* vertices;
int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
if (scale_x == 0)
*yoff = iy0;
if (gbm.w && gbm.h) {
- gbm.pixels = (unsigned char *)STBTT_malloc(gbm.w * gbm.h, info->userdata);
+ gbm.pixels = (unsigned char*)STBTT_malloc(gbm.w * gbm.h, info->userdata);
if (gbm.pixels) {
gbm.stride = gbm.w;
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) {
+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,
+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;
+ stbtt_vertex* vertices;
int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
stbtt__bitmap gbm;
STBTT_free(vertices, info->userdata);
}
-STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h,
+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) {
+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,
+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) {
+ 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,
+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) {
+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,
+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)
+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
+ unsigned char* pixels, int pw, int ph, // bitmap to be filled in
int first_char, int num_chars, // characters to bake
- stbtt_bakedchar *chardata) {
+ stbtt_bakedchar* chardata) {
float scale;
int x, y, bottom_y, i;
stbtt_fontinfo f;
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) {
+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;
+ 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);
int id, w, h, was_packed;
};
-static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) {
+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;
STBTT__NOTUSED(num_nodes);
}
-static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) {
+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) {
// 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);
+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);
+ stbrp_node* nodes = (stbrp_node*)STBTT_malloc(sizeof(*nodes) * num_nodes, alloc_context);
if (context == NULL || nodes == NULL) {
if (context != NULL)
return 1;
}
-STBTT_DEF void stbtt_PackEnd(stbtt_pack_context *spc) {
+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,
+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);
spc->v_oversample = v_oversample;
}
-STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) { spc->skip_missing = skip; }
+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) {
+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;
}
}
-static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) {
+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;
}
// 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) {
+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;
return k;
}
-STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w,
+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) {
+ 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);
}
// 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) {
+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
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];
+ stbrp_rect* r = &rects[k];
if (r->was_packed && r->w != 0 && r->h != 0) {
- stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
+ 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
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_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;
+ stbrp_rect* rects;
// flag all characters as NOT packed
for (i = 0; i < num_ranges; ++i)
for (i = 0; i < num_ranges; ++i)
n += ranges[i].num_chars;
- rects = (stbrp_rect *)STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
+ rects = (stbrp_rect*)STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
if (rects == NULL)
return 0;
return return_value;
}
-STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index,
+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_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;
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) {
+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;
*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) {
+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;
+ const stbtt_packedchar* b = chardata + char_index;
if (align_to_integer) {
float x = (float)STBTT_ifloor((*xpos + b->xoff) + 0.5f);
}
}
-static int equal(float *a, float *b) { return (a[0] == b[0] && a[1] == b[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) {
+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;
}
// x^3 + a*x^2 + b*x + c = 0
-static int stbtt__solve_cubic(float a, float b, float c, float *r) {
+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;
}
}
-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_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;
+ unsigned char* data;
if (scale == 0)
return NULL;
{
int x, y, i, j;
- float *precompute;
- stbtt_vertex *verts;
+ 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);
+ 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) {
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) {
+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,
+static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8* s1, stbtt_int32 len1, stbtt_uint8* s2,
stbtt_int32 len2) {
stbtt_int32 i = 0;
return -1;
if (s1[i++] != 0x80 + ((c >> 6) & 0x3f))
return -1;
- if (s1[i++] != 0x80 + ((c)&0x3f))
+ if (s1[i++] != 0x80 + ((c) & 0x3f))
return -1;
s2 += 2; // plus another 2 below
len2 -= 2;
return -1;
if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f))
return -1;
- if (s1[i++] != 0x80 + ((ch)&0x3f))
+ if (s1[i++] != 0x80 + ((ch) & 0x3f))
return -1;
}
s2 += 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 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,
+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_uint8* fc = font->data;
stbtt_uint32 offset = font->fontstart;
stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
if (!nm)
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 (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,
+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);
return 1;
} else if (matchlen < nlen && name[matchlen] == ' ') {
++matchlen;
- if (stbtt_CompareUTF8toUTF16_bigendian_internal((char *)(name + matchlen), nlen - matchlen,
- (char *)(fc + stringOffset + off), slen))
+ if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*)(name + matchlen), nlen - matchlen,
+ (char*)(fc + stringOffset + off), slen))
return 1;
}
} else {
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);
+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) {
+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))
+ if (stbtt__matches((stbtt_uint8*)font_collection, off, (stbtt_uint8*)name_utf8, flags))
return off;
}
}
#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,
+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__)
// compute perpendicular vector
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) {
+vkvg_inline void vec2_inv(vec2* v) {
v->x = -v->x;
v->y = -v->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); }
+vkvg_inline float mat2_det(mat2* m) { return (m->row0.x * m->row1.y) - (m->row0.y * m->row1.y); }
#endif
if (ctx->pSurf->newSurf) {
ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearAll;
- ctx->pSurf->newSurf = false;
+ ctx->pSurf->newSurf = false;
} else {
ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearStencil;
}
ctx->cmdStarted = false;
ctx->curClipState = vkvg_clip_state_none;
-
ctx->vertCount = ctx->indCount = 0;
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
ctx->timelineStep = 0;
LOG(VKVG_LOG_ERR, "CREATE Context failed, invalid surface\n");
return (VkvgContext)&_vkvg_status_invalid_surface;
}
- VkvgDevice dev = surf->dev;
+ VkvgDevice dev = surf->dev;
if (vkvg_device_status(dev)) {
LOG(VKVG_LOG_ERR, "CREATE Context failed, invalid device\n");
return (VkvgContext)&_vkvg_status_device_error;
VkvgContext ctx = NULL;
if (_device_try_get_cached_context(dev, &ctx)) {
- ctx->pSurf = surf;
+ ctx->pSurf = surf;
ctx->status = VKVG_STATUS_SUCCESS;
_init_ctx(ctx);
_update_descriptor_set(ctx, surf->dev->emptyImg, ctx->dsSrc);
ctx->cmd = ctx->cmdBuffers[0]; // current recording buffer
return ctx;
}
- ctx = (vkvg_context *)calloc(1, sizeof(vkvg_context));
+ ctx = (vkvg_context*)calloc(1, sizeof(vkvg_context));
if (!ctx) {
LOG(VKVG_LOG_ERR, "CREATE context failed, no memory\n");
ctx->dev = surf->dev;
- 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) {
if (ctx->points)
void _clear_context(VkvgContext ctx) {
// free saved context stack elmt
- vkvg_context_save_t *next = ctx->pSavedCtxs;
+ vkvg_context_save_t* next = ctx->pSavedCtxs;
ctx->pSavedCtxs = NULL;
while (next != NULL) {
- vkvg_context_save_t *cur = next;
+ vkvg_context_save_t* cur = next;
next = cur->pNext;
_free_ctx_save(cur);
}
if (ctx->dev->threadAware)
mtx_lock(&ctx->dev->mutex);
- vkvg_debug_stats_t *dbgstats = &ctx->dev->debug_stats;
+ vkvg_debug_stats_t* dbgstats = &ctx->dev->debug_stats;
if (dbgstats->sizePoints < ctx->sizePoints)
dbgstats->sizePoints = ctx->sizePoints;
if (dbgstats->sizePathes < ctx->sizePathes)
return false;
return !_current_path_is_empty(ctx);
}
-void vkvg_get_current_point(VkvgContext ctx, float *x, float *y) {
+void vkvg_get_current_point(VkvgContext ctx, float* x, float* y) {
if (vkvg_status(ctx))
return;
assert(x);
_set_curve_end(ctx);
}
const double quadraticFact = 2.0 / 3.0;
-void _quadratic_to(VkvgContext ctx, float x1, float y1, float x2, float y2) {
+void _quadratic_to(VkvgContext ctx, float x1, float y1, float x2, float y2) {
float x0, y0;
if (_current_path_is_empty(ctx)) {
x0 = x1;
vkvg_close_path(ctx);
}
-void vkvg_path_extents(VkvgContext ctx, float* const x1, float *const y1, float *const x2, float *const y2) {
+void vkvg_path_extents(VkvgContext ctx, float* const x1, float* const y1, float* const x2, float* const y2) {
if (vkvg_status(ctx))
return;
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* inds = &ctx->indexCache[ctx->indCount - 6];
VKVG_IBO_INDEX_TYPE ii = str.firstIdx;
if (inverse) {
inds[1] = ii + 1;
return 0;
return ctx->miterLimit;
}
-void vkvg_set_dash(VkvgContext ctx, const float *dashes, uint32_t num_dashes, float offset) {
+void vkvg_set_dash(VkvgContext ctx, const float* dashes, uint32_t num_dashes, float offset) {
if (vkvg_status(ctx))
return;
if (ctx->dashCount > 0)
ctx->dashOffset = offset;
if (ctx->dashCount == 0)
return;
- ctx->dashes = (float *)malloc(sizeof(float) * ctx->dashCount);
+ 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) {
+void vkvg_get_dash(VkvgContext ctx, const float* dashes, uint32_t* num_dashes, float* offset) {
if (vkvg_status(ctx))
return;
*num_dashes = ctx->dashCount;
*offset = ctx->dashOffset;
if (ctx->dashCount == 0 || dashes == NULL)
return;
- memcpy((float *)dashes, ctx->dashes, sizeof(float) * ctx->dashCount);
+ memcpy((float*)dashes, ctx->dashes, sizeof(float) * ctx->dashCount);
}
vkvg_line_cap_t vkvg_get_line_cap(VkvgContext ctx) {
return ctx->pattern;
}
-void vkvg_select_font_face(VkvgContext ctx, const char *name) {
+void vkvg_select_font_face(VkvgContext ctx, const char* name) {
if (vkvg_status(ctx))
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) {
+void vkvg_load_font_from_path(VkvgContext ctx, const char* path, const char* name) {
if (vkvg_status(ctx))
return;
RECORD(ctx, VKVG_CMD_SET_FONT_PATH, name);
- _vkvg_font_identity_t *fid = _font_cache_add_font_identity(ctx, 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) {
+void vkvg_load_font_from_memory(VkvgContext ctx, unsigned char* fontBuffer, long fontBufferByteSize, const char* name) {
if (vkvg_status(ctx))
return;
// RECORD(ctx, VKVG_CMD_SET_FONT_PATH, name);
- _vkvg_font_identity_t *fid = _font_cache_add_font_identity(ctx, NULL, name);
+ _vkvg_font_identity_t* fid = _font_cache_add_font_identity(ctx, NULL, name);
fid->fontBuffer = fontBuffer;
fid->fontBufSize = fontBufferByteSize;
ctx->currentFontSize = NULL;
}
-void vkvg_set_text_direction(vkvg_context *ctx, vkvg_direction_t direction) {}
+void vkvg_set_text_direction(vkvg_context* ctx, vkvg_direction_t direction) {}
-void vkvg_show_text(VkvgContext ctx, const char *text) {
+void vkvg_show_text(VkvgContext ctx, const char* text) {
if (vkvg_status(ctx))
return;
RECORD(ctx, VKVG_CMD_SHOW_TEXT, text);
//_flush_undrawn_vertices (ctx);
}
-VkvgText vkvg_text_run_create(VkvgContext ctx, const char *text) {
+VkvgText vkvg_text_run_create(VkvgContext ctx, const char* text) {
if (vkvg_status(ctx))
return NULL;
- VkvgText tr = (vkvg_text_run_t *)calloc(1, sizeof(vkvg_text_run_t));
+ 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) {
+VkvgText vkvg_text_run_create_with_length(VkvgContext ctx, const char* text, uint32_t length) {
if (vkvg_status(ctx))
return NULL;
- VkvgText tr = (vkvg_text_run_t *)calloc(1, sizeof(vkvg_text_run_t));
+ 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) {
+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));
#else
- *pGlyphInfo = textRun->glyphs[index];
+ *pGlyphInfo = textRun->glyphs[index];
#endif
}
void vkvg_text_run_destroy(VkvgText textRun) {
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_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) {
+void vkvg_text_extents(VkvgContext ctx, const char* text, vkvg_text_extents_t* extents) {
if (vkvg_status(ctx))
return;
_font_cache_text_extents(ctx, text, -1, extents);
}
-void vkvg_font_extents(VkvgContext ctx, vkvg_font_extents_t *extents) {
+void vkvg_font_extents(VkvgContext ctx, vkvg_font_extents_t* extents) {
if (vkvg_status(ctx))
return;
_font_cache_font_extents(ctx, extents);
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));
+ 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)) {
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;
+ VkhImage* savedStencilsPtr = NULL;
if (savedStencilsPtr)
- savedStencilsPtr = (VkhImage *)realloc(ctx->savedStencils, curSaveStencil * sizeof(VkhImage));
+ savedStencilsPtr = (VkhImage*)realloc(ctx->savedStencils, curSaveStencil * sizeof(VkhImage));
else
- savedStencilsPtr = (VkhImage *)malloc(curSaveStencil * sizeof(VkhImage));
+ savedStencilsPtr = (VkhImage*)malloc(curSaveStencil * sizeof(VkhImage));
if (savedStencilsPtr == NULL) {
free(sav);
ctx->status = VKVG_STATUS_NO_MEMORY;
sav->dashOffset = ctx->dashOffset;
sav->dashCount = ctx->dashCount;
if (ctx->dashCount > 0) {
- sav->dashes = (float *)malloc(sizeof(float) * ctx->dashCount);
+ sav->dashes = (float*)malloc(sizeof(float) * ctx->dashCount);
memcpy(sav->dashes, ctx->dashes, sizeof(float) * ctx->dashCount);
}
sav->lineWidth = ctx->lineWidth;
LOG(VKVG_LOG_INFO, "RESTORE CONTEXT: ctx = %p\n", ctx);
- vkvg_context_save_t *sav = ctx->pSavedCtxs;
+ vkvg_context_save_t* sav = ctx->pSavedCtxs;
ctx->pSavedCtxs = sav->pNext;
_flush_cmd_buff(ctx);
free(ctx->dashes);
ctx->dashCount = sav->dashCount;
if (ctx->dashCount > 0) {
- ctx->dashes = (float *)malloc(sizeof(float) * ctx->dashCount);
+ ctx->dashes = (float*)malloc(sizeof(float) * ctx->dashCount);
memcpy(ctx->dashes, sav->dashes, sizeof(float) * ctx->dashCount);
}
vkvg_matrix_rotate(&ctx->pushConsts.mat, radians);
_set_mat_inv_and_vkCmdPush(ctx);
}
-void vkvg_transform(VkvgContext ctx, const vkvg_matrix_t *matrix) {
+void vkvg_transform(VkvgContext ctx, const vkvg_matrix_t* matrix) {
if (vkvg_status(ctx))
return;
RECORD(ctx, VKVG_CMD_TRANSFORM, matrix);
ctx->pushConsts.mat = im;
_set_mat_inv_and_vkCmdPush(ctx);
}
-void vkvg_set_matrix(VkvgContext ctx, const vkvg_matrix_t *matrix) {
+void vkvg_set_matrix(VkvgContext ctx, const vkvg_matrix_t* matrix) {
if (vkvg_status(ctx))
return;
RECORD(ctx, VKVG_CMD_SET_MATRIX, matrix);
ctx->pushConsts.mat = (*matrix);
_set_mat_inv_and_vkCmdPush(ctx);
}
-void vkvg_get_matrix(VkvgContext ctx, vkvg_matrix_t *const matrix) {
+void vkvg_get_matrix(VkvgContext ctx, vkvg_matrix_t* const matrix) {
if (vkvg_status(ctx) || !matrix)
return;
*matrix = ctx->pushConsts.mat;
return ctx->pSurf;
}
-const char *vkvg_status_to_string(vkvg_status_t status) {
+const char* vkvg_status_to_string(vkvg_status_t status) {
switch (status) {
case VKVG_STATUS_SUCCESS:
return "no error has occurred";
#endif
void _resize_vertex_cache(VkvgContext ctx, uint32_t newSize) {
- Vertex *tmp = (Vertex *)realloc(ctx->vertexCache, (size_t)newSize * sizeof(Vertex));
+ 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);
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));
+ 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) {
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));
+ 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;
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));
+ 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;
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];
+ Vertex* pVert = &ctx->vertexCache[ctx->vertCount];
pVert->pos.x = x;
pVert->pos.y = y;
pVert->color = ctx->curColor;
_check_vertex_cache_size(ctx);
}
void _add_vertexf_unchecked(VkvgContext ctx, float x, float y) {
- Vertex *pVert = &ctx->vertexCache[ctx->vertCount];
+ Vertex* pVert = &ctx->vertexCache[ctx->vertCount];
pVert->pos.x = x;
pVert->pos.y = y;
pVert->color = ctx->curColor;
_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];
+ 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;
_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];
+ VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount];
if (odd) {
inds[0] = ctx->indexCache[ctx->indCount - 2];
inds[1] = i;
}
#endif
void _add_tri_indices_for_rect(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i) {
- VKVG_IBO_INDEX_TYPE *inds = &ctx->indexCache[ctx->indCount];
+ VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount];
inds[0] = i;
inds[1] = i + 2;
inds[2] = i + 1;
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];
+ VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount];
inds[0] = i0;
inds[1] = i1;
inds[2] = i2;
}
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];
+ VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount];
inds[0] = i0;
inds[1] = i1;
inds[2] = i2;
{{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];
+ Vertex* pVert = &ctx->vertexCache[ctx->vertCount];
memcpy(pVert, v, 4 * sizeof(Vertex));
ctx->vertCount += 4;
ctx->pushConsts.source = bounds;
// transform control point with current ctx matrix
- vkvg_gradient_t grad = *(vkvg_gradient_t *)pat->data;
+ vkvg_gradient_t grad = *(vkvg_gradient_t*)pat->data;
if (grad.count < 2) {
ctx->status = VKVG_STATUS_PATTERN_INVALID_GRADIENT;
free(ctx);
}
// populate vertice buff for stroke
-bool _build_vb_step(VkvgContext ctx, stroke_context_t *str, bool isCurve) {
+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]);
return (det < 0);
}
-void _draw_stoke_cap(VkvgContext ctx, stroke_context_t *str, vec2 p0, vec2 n, bool isStart) {
+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);
}
}
}
-float _draw_dashed_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) {
// vec2 pL = ctx->points[str->iL];
vec2 p = ctx->points[str->cp];
vec2 pR = ctx->points[str->iR];
dc->curDashOffset = fmodf(dc->curDashOffset, dc->totDashLength);
return segmentLength;
}
-void _draw_segment(VkvgContext ctx, stroke_context_t *str, dash_context_t *dc, bool isCurve) {
+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);
return (s >= 0) && (t >= 0) && (s + t <= D);
}
-void _free_ctx_save(vkvg_context_save_t *sav) {
+void _free_ctx_save(vkvg_context_save_t* sav) {
if (sav->dashCount > 0)
free(sav->dashes);
if (sav->pattern)
}
// Even-Odd inside test with stencil buffer implementation.
-void _poly_fill(VkvgContext ctx, vec4 *bounds) {
+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) {
_add_indice(ctx, i);
}
void skip_vertex2(VKVG_IBO_INDEX_TYPE v, VkvgContext ctx) {}
-void begin2(GLenum which, void *poly_data) {
+void begin2(GLenum which, void* poly_data) {
VkvgContext ctx = (VkvgContext)poly_data;
switch (which) {
case GL_TRIANGLES:
}
}
-void combine2(const GLdouble newVertex[3], const void *neighborVertex_s[4], const GLfloat neighborWeight[4],
- void **outData, void *poly_data) {
+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));
+ *outData = (void*)((unsigned long)(ctx->vertCount - ctx->curVertOffset));
_add_vertex(ctx, v);
}
-void vertex2(void *vertex_data, void *poly_data) {
+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);
return;
}
- GLUtesselator *tess = gluNewTess();
+ 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);
+ 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);
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));
+ gluTessVertex(tess, dp, (void*)((unsigned long)firstVertIdx + i));
i++;
}
gluTessEndContour(tess);
ecps[i] = ecp;
_add_vertex(ctx, v);
- ear_clip_point *ecp_current = ecps;
+ ear_clip_point* ecp_current = ecps;
uint32_t tries = 0;
while (ecps_count > 3) {
tries++;
continue;
}
- ear_clip_point *vP = v2->next;
+ ear_clip_point* vP = v2->next;
bool isEar = true;
while (vP != v1) {
if (ptInTriangle(vP->pos, v0->pos, v2->pos, v1->pos)) {
}
#endif
-void _vkvg_path_extents(VkvgContext ctx, bool transformed, float *x1, float *y1, float *x2, float *y2) {
+void _vkvg_path_extents(VkvgContext ctx, bool transformed, float* x1, float* y1, float* x2, float* y2) {
uint32_t ptrPath = 0;
uint32_t firstPtIdx = 0;
*y2 = yMax;
}
-void _draw_full_screen_quad(VkvgContext ctx, vec4 *scissor) {
+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
_ensure_vertex_cache_size(ctx, 3);
_add_vertexf_unchecked(ctx, -1, -1);
- _add_vertexf_unchecked(ctx, 3, -1);
- _add_vertexf_unchecked(ctx, -1, 3);
+ _add_vertexf_unchecked(ctx, 3, -1);
+ _add_vertexf_unchecked(ctx, -1, 3);
ctx->curVertOffset = ctx->vertCount;
#endif
}
-void _select_font_face(VkvgContext ctx, const char *name) {
+void _select_font_face(VkvgContext ctx, const char* name) {
if (strcmp(ctx->selectedFontName, name) == 0)
return;
strcpy(ctx->selectedFontName, name);
#define FULLSCREEN_BIT 0x10000000
#define SRCTYPE_MASK 0x000000FF
-#define CreateRgba(r, g, b, a) (((a&0xFF) << 24) | ((r&0xFF) << 16) | ((g&0xFF) << 8) | b)
+#define CreateRgba(r, g, b, a) (((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | b)
#ifdef VKVG_PREMULT_ALPHA
#define CreateRgbaf(r, g, b, a) \
- ((((uint32_t)(a * 255.0f)&0xFF) << 24) | (((uint32_t)(b * a * 255.0f)&0xFF) << 16) | (((uint32_t)(g * a * 255.0f)&0xFF) << 8) | ((uint32_t)(r * a * 255.0f)&0xFF))
+ ((((uint32_t)(a * 255.0f) & 0xFF) << 24) | (((uint32_t)(b * a * 255.0f) & 0xFF) << 16) | \
+ (((uint32_t)(g * a * 255.0f) & 0xFF) << 8) | ((uint32_t)(r * a * 255.0f) & 0xFF))
#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))
} vkvg_clip_state_t;
typedef struct _vkvg_context_save_t {
- struct _vkvg_context_save_t *pNext;
+ struct _vkvg_context_save_t* pNext;
float lineWidth;
float miterLimit;
float dashOffset; // an offset for dash
- float *dashes; // an array of alternate lengths of on and off stroke.
+ float* dashes; // an array of alternate lengths of on and off stroke.
uint32_t dashCount; // value count in dash array, 0 if dash not set.
vkvg_operator_t curOperator;
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_font_identity_t* currentFont; // font ready for lookup
vkvg_direction_t textDirection;
push_constants pushConsts;
uint32_t curColor;
#endif
#if VKVG_RECORDING
- vkvg_recording_t *recording;
+ vkvg_recording_t* recording;
#endif
vkh_buffer_t uboGrad; // uniform buff obj holdings gradient infos
uint32_t sizeVertices; // reserved size
uint32_t vertCount; // effective vertices count
- Vertex *vertexCache;
- VKVG_IBO_INDEX_TYPE *indexCache;
+ Vertex* vertexCache;
+ VKVG_IBO_INDEX_TYPE* indexCache;
// pathes, exists until stroke of fill
- vec2 *points; // points array
+ 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* 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.
- bool cmdStarted; // prevent flushing empty renderpass
- bool pushCstDirty; // prevent pushing to gpu if not requested
+ bool cmdStarted; // prevent flushing empty renderpass
+ bool pushCstDirty; // prevent pushing to gpu if not requested
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.
+ float* dashes; // an array of alternate lengths of on and off stroke.
vkvg_operator_t curOperator;
vkvg_line_cap_t lineCap;
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_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.
+ 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;
typedef struct _ear_clip_point {
vec2 pos;
VKVG_IBO_INDEX_TYPE idx;
- struct _ear_clip_point *next;
+ struct _ear_clip_point* next;
} ear_clip_point;
typedef struct {
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 _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 _poly_fill(VkvgContext ctx, vec4* bounds);
void _fill_non_zero(VkvgContext ctx);
-void _draw_full_screen_quad(VkvgContext ctx, vec4 *scissor);
+void _draw_full_screen_quad(VkvgContext ctx, vec4* scissor);
void _create_gradient_buff(VkvgContext ctx);
void _create_vertices_buff(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 _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 ecp_zcross(ear_clip_point *p0, ear_clip_point *p1, ear_clip_point *p2) {
+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,
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 _select_font_face(VkvgContext ctx, const char* name);
#endif
}
#define _CHECK_INST_EXT(ext) \
-if (vkh_instance_extension_supported(#ext)) { \
+ if (vkh_instance_extension_supported(#ext)) { \
if (pExtensions) \
- pExtensions[*pExtCount] = #ext; \
+ pExtensions[*pExtCount] = #ext; \
(*pExtCount)++; \
-}
+ }
#define _CHECK_DEV_EXT(ext) \
-{ \
+ { \
if (_get_dev_extension_is_supported(pExtensionProperties, extensionCount, #ext)) { \
if (pExtensions) \
- pExtensions[*pExtCount] = #ext; \
+ pExtensions[*pExtCount] = #ext; \
(*pExtCount)++; \
- } \
-}
+ } \
+ }
void vkvg_device_set_context_cache_size(VkvgDevice dev, uint32_t maxCount) {
if (maxCount == dev->cachedContextMaxCount)
dev->cachedContextMaxCount = maxCount;
- _cached_ctx *cur = dev->cachedContextLast;
+ _cached_ctx* cur = dev->cachedContextLast;
while (cur && dev->cachedContextCount > dev->cachedContextMaxCount) {
_release_context_ressources(cur->ctx);
- _cached_ctx *prev = cur;
+ _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) {
+void _device_init(VkvgDevice dev, const vkvg_device_create_info_t* info) {
dev->vkDev = info->vkdev;
dev->phy = info->phy;
dev->instance = info->inst;
#ifdef VKH_USE_VMA
VmaAllocatorCreateInfo allocatorInfo = {.physicalDevice = info->phy, .device = info->vkdev};
- vmaCreateAllocator(&allocatorInfo, (VmaAllocator *)&dev->allocator);
+ vmaCreateAllocator(&allocatorInfo, (VmaAllocator*)&dev->allocator);
#endif
dev->cmdPool = vkh_cmd_pool_create(vkhd, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
dev->status = VKVG_STATUS_SUCCESS;
}
-
-void vkvg_get_required_instance_extensions(const char **pExtensions, uint32_t *pExtCount) {
+void vkvg_get_required_instance_extensions(const char** pExtensions, uint32_t* pExtCount) {
*pExtCount = 0;
vkh_instance_extensions_check_init();
vkh_instance_extensions_check_release();
}
-bool _get_dev_extension_is_supported(VkExtensionProperties *pExtensionProperties, uint32_t extensionCount,
- const char *name) {
+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;
}
-
-vkvg_status_t vkvg_get_required_device_extensions(VkPhysicalDevice phy, const char **pExtensions, uint32_t *pExtCount) {
- VkExtensionProperties *pExtensionProperties;
+vkvg_status_t vkvg_get_required_device_extensions(VkPhysicalDevice phy, const char** pExtensions, uint32_t* pExtCount) {
+ VkExtensionProperties* pExtensionProperties;
uint32_t extensionCount;
*pExtCount = 0;
VK_CHECK_RESULT(vkEnumerateDeviceExtensionProperties(phy, NULL, &extensionCount, NULL));
- pExtensionProperties = (VkExtensionProperties *)malloc(extensionCount * sizeof(VkExtensionProperties));
+ 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
}
// enabledFeature12 is guarantied to be the first in pNext chain
-const void *vkvg_get_device_requirements(VkPhysicalDeviceFeatures *pEnabledFeatures) {
+const void* vkvg_get_device_requirements(VkPhysicalDeviceFeatures* pEnabledFeatures) {
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 = {
#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;
+ scalarBlockFeat.pNext = pNext;
+ pNext = &scalarBlockFeat;
#endif
#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
static VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timelineSemaFeat = {
return pNext;
}
-VkvgDevice vkvg_device_create(vkvg_device_create_info_t *info) {
+VkvgDevice vkvg_device_create(vkvg_device_create_info_t* info) {
LOG(VKVG_LOG_INFO, "CREATE Device\n");
if (!info) {
LOG(VKVG_LOG_ERR, "CREATE Device failed, provided vkvg_device_create_info_t is null\n");
return (VkvgDevice)&_vkvg_status_invalid_dev_ci;
}
- VkvgDevice dev = (vkvg_device *)calloc(1, sizeof(vkvg_device));
+ VkvgDevice dev = (vkvg_device*)calloc(1, sizeof(vkvg_device));
if (!dev) {
LOG(VKVG_LOG_ERR, "CREATE Device failed, no memory\n");
return (VkvgDevice)&_vkvg_status_no_memory;
}
if (!info->vkdev) {
- const char *enabledExts[10];
- const char *enabledLayers[10];
+ const char* enabledExts[10];
+ const char* enabledLayers[10];
uint32_t enabledExtsCount = 0, enabledLayersCount = 0, phyCount = 0;
vkh_layers_check_init();
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);
}
VkPhysicalDeviceFeatures enabledFeatures = {0};
- const void *pNext = vkvg_get_device_requirements(&enabledFeatures);
+ const void* pNext = vkvg_get_device_requirements(&enabledFeatures);
VkDeviceCreateInfo device_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.queueCreateInfoCount = qCount,
- .pQueueCreateInfos = (VkDeviceQueueCreateInfo *)&pQueueInfos,
+ .pQueueCreateInfos = (VkDeviceQueueCreateInfo*)&pQueueInfos,
.enabledExtensionCount = enabledExtsCount,
.ppEnabledExtensionNames = enabledExts,
.pEnabledFeatures = &enabledFeatures,
LOG(VKVG_LOG_INFO, "DESTROY Device\n");
if (dev->cachedContextCount > 0) {
- _cached_ctx *cur = dev->cachedContextLast;
+ _cached_ctx* cur = dev->cachedContextLast;
while (cur) {
assert(cur->ctx->status == VKVG_STATUS_IN_CACHE);
cur->ctx->status = VKVG_STATUS_SUCCESS;
_release_context_ressources(cur->ctx);
- _cached_ctx *prev = cur;
+ _cached_ctx* prev = cur;
cur = cur->pNext;
free(prev);
}
// TODO: reset font cache
}
-void vkvg_device_get_dpy(VkvgDevice dev, int *hdpy, int *vdpy) {
+void vkvg_device_get_dpy(VkvgDevice dev, int* hdpy, int* vdpy) {
if (vkvg_device_status(dev))
return;
*hdpy = dev->hdpi;
PFN_vkResetFences ResetFences;
PFN_vkResetCommandBuffer ResetCommandBuffer;
-bool _device_try_get_phyinfo(VkhPhyInfo *phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo *phy) {
+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];
VkShaderModule modVert, modFrag;
#endif
VkShaderModuleCreateInfo createInfo = {.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
- .pCode = (uint32_t *)vkvg_main_vert_spv,
+ .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.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.pCode = (uint32_t*)vkvg_main_frag_spv;
createInfo.codeSize = vkvg_main_frag_spv_len;
#endif
VK_CHECK_RESULT(vkCreateShaderModule(dev->vkDev, &createInfo, NULL, &modFrag));
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));
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.pushConstantRangeCount = 1,
.pPushConstantRanges =
- (VkPushConstantRange *)&pushConstantRange,
+ (VkPushConstantRange*)&pushConstantRange,
.setLayoutCount = 3,
.pSetLayouts = dsls};
VK_CHECK_RESULT(vkCreatePipelineLayout(dev->vkDev, &pipelineLayoutCreateInfo, NULL, &dev->pipelineLayout));
ResetFences(dev->vkDev, 1, &dev->fence);
}
-bool _device_try_get_cached_context(VkvgDevice dev, VkvgContext *pCtx) {
+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;
+ _cached_ctx* prev = NULL;
+ _cached_ctx* cur = dev->cachedContextLast;
while (cur) {
if (thrd_equal(cur->thread, curThread)) {
if (prev)
LOCK_DEVICE
- _cached_ctx *cur = (_cached_ctx *)calloc(1, sizeof(_cached_ctx));
+ _cached_ctx* cur = (_cached_ctx*)calloc(1, sizeof(_cached_ctx));
cur->ctx = ctx;
cur->thread = thrd_current();
cur->pNext = dev->cachedContextLast;
UNLOCK_DEVICE
}
-void _device_submit_cmd(VkvgDevice dev, VkCommandBuffer *cmd, VkFence fence) {
+void _device_submit_cmd(VkvgDevice dev, VkCommandBuffer* cmd, VkFence fence) {
LOCK_DEVICE
vkh_cmd_submit(dev->gQueue, cmd, fence);
UNLOCK_DEVICE
typedef struct _cached_ctx {
thrd_t thread;
VkvgContext ctx;
- struct _cached_ctx *pNext;
+ struct _cached_ctx* pNext;
} _cached_ctx;
typedef struct _vkvg_device_t {
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 */
VkSampleCountFlags samples; /**< samples count common to all surfaces */
bool deferredResolve; /**< if true, resolve only on context destruction and set as source */
- _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*/
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.*/
+ _cached_ctx* cachedContextLast; /**< Last element of single linked list of saved context for fast reuse.*/
#ifdef VKVG_WIRED_DEBUG
VkPipeline pipelineWired;
if (dev->threadAware) \
mtx_unlock(&dev->mutex);
-bool _device_try_get_phyinfo(VkhPhyInfo *phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo *phy);
+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_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);
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);
+void _device_submit_cmd(VkvgDevice dev, VkCommandBuffer* cmd, VkFence fence);
-bool _device_try_get_cached_context(VkvgDevice dev, VkvgContext *pCtx);
+bool _device_try_get_cached_context(VkvgDevice dev, VkvgContext* pCtx);
void _device_store_context(VkvgContext ctx);
#endif
static int defaultFontCharSize = 12 << 6;
void _fonts_cache_create(VkvgDevice dev) {
- _font_cache_t *cache = (_font_cache_t *)calloc(1, sizeof(_font_cache_t));
+ _font_cache_t* cache = (_font_cache_t*)calloc(1, sizeof(_font_cache_t));
if (dev->threadAware)
mtx_init(&cache->mutex, mtx_plain);
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;
}
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);
_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);
}
// 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) {
+void _flush_chars_to_tex(VkvgDevice dev, _vkvg_font_t* f) {
- _font_cache_t *cache = dev->fontCache;
+ _font_cache_t* cache = dev->fontCache;
if (cache->stagingX == 0) // no char in stagging buff to flush
return;
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;
+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)
_init_next_line_in_tex_cache(dev, f);
}
void _font_cache_destroy(VkvgDevice dev) {
- _font_cache_t *cache = (_font_cache_t *)dev->fontCache;
+ _font_cache_t* cache = (_font_cache_t*)dev->fontCache;
free(cache->hostBuff);
for (int i = 0; i < cache->fontsCount; ++i) {
- _vkvg_font_identity_t *f = &cache->fonts[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];
+ _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)
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;
+_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));
uint32_t bmpByteWidth = bmp.width;
uint32_t bmpPixelWidth = bmp.width;
uint32_t bmpRows = bmp.rows;
- unsigned char *buffer = bmp.buffer;
+ unsigned char* buffer = bmp.buffer;
#if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
bmpPixelWidth /= 3;
#endif
#else
- stbtt_fontinfo *pStbInfo = &tr->fontId->stbInfo;
+ 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);
}
- _char_ref *cr = (_char_ref *)malloc(sizeof(_char_ref));
+ _char_ref* cr = (_char_ref*)malloc(sizeof(_char_ref));
int penX = dev->fontCache->stagingX;
#ifdef VKVG_USE_FREETYPE
cr->bmpDiff.y = (int16_t)slot->bitmap_top;
cr->advance = slot->advance;
#else
- int advance;
- int lsb;
+ 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;
dev->fontCache->stagingX += bmpPixelWidth;
return cr;
}
-void _font_add_name(_vkvg_font_identity_t *font, const char *name) {
+void _font_add_name(_vkvg_font_identity_t* font, const char* name) {
if (++font->namesCount == 1)
- font->names = (char **)malloc(sizeof(char *));
+ 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));
+ 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");
+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);
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;
+_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));
+ 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));
+ 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));
+ nf.fontFile = (char*)malloc(fflength * sizeof(char));
strcpy(nf.fontFile, fontFilePath);
}
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;
+_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)
}
// if not found, create a new font size structure
if (++font->sizeCount == 1)
- font->sizes = (_vkvg_font_t *)malloc(sizeof(_vkvg_font_t));
+ 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));
+ 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;
+ _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;
#else
- int result = stbtt_InitFont(&font->stbInfo, font->fontBuffer, 0);
+ 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.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));
}
// 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;
+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) {
}
#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;
+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);
+ FcPattern* pat = FcNameParse((const FcChar8*)ctx->selectedFontName);
FcConfigSubstitute(cache->config, pat, FcMatchPattern);
FcDefaultSubstitute(pat);
FcResult result;
- FcPattern *font = FcFontMatch(cache->config, pat, &result);
+ FcPattern* font = FcFontMatch(cache->config, pat, &result);
if (font)
- FcPatternGetString(font, FC_FILE, 0, (FcChar8 **)&fontFile);
+ FcPatternGetString(font, FC_FILE, 0, (FcChar8**)&fontFile);
*resolvedFont = NULL;
if (fontFile) {
// try find font in cache by path
}
if (!*resolvedFont) {
// if not found, create a new vkvg_font
- _vkvg_font_identity_t *fid = _font_cache_add_font_identity(ctx, fontFile, ctx->selectedFontName);
+ _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];
}
#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();
+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();
+ 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);
#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) {
+void _font_cache_font_extents(VkvgContext ctx, vkvg_font_extents_t* extents) {
_update_current_font(ctx);
if (ctx->status)
return;
// TODO: ensure correct metrics are returned (scalled/unscalled, etc..)
- _vkvg_font_t *font = ctx->currentFontSize;
+ _vkvg_font_t* font = ctx->currentFontSize;
#ifdef VKVG_USE_FREETYPE
- FT_BBox *bbox = &font->face->bbox;
- FT_Size_Metrics *metrics = &font->face->size->metrics;
+ 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;
#endif
}
// compute text extends for provided string.
-void _font_cache_text_extents(VkvgContext ctx, const char *text, int length, vkvg_text_extents_t *extents) {
+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;
}
// 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) {
+void _font_cache_create_text_run(VkvgContext ctx, const char* text, int length, VkvgText textRun) {
_update_current_font(ctx);
wsize = mbstowcs(NULL, text, 0);
else
wsize = (size_t)length;
- wchar_t *tmp = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t));
+ 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));
+ 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]);
#endif
- _char_ref *cr = textRun->font->charLookup[gindex];
+ _char_ref* cr = textRun->font->charLookup[gindex];
if (cr == NULL)
cr = _prepare_char(textRun->dev, textRun, gindex);
textRun->glyphs[i].codepoint = gindex;
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;
+ 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
#endif
}
#ifdef DEBUG
-void _show_texture(vkvg_context *ctx) {
+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];
+ Vertex* pVert = &ctx->vertexCache[ctx->vertCount];
memcpy(pVert, vs, 4 * sizeof(Vertex));
ctx->vertCount += 4;
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;
+ vkvg_glyph_info_t* glyph_info = tr->glyphs;
glyph_count = tr->glyph_count;
#endif
LOCK_FONTCACHE(ctx->dev)
for (uint32_t i = 0; i < glyph_count; ++i) {
- _char_ref *cr = tr->font->charLookup[glyph_info[i].codepoint];
+ _char_ref* cr = tr->font->charLookup[glyph_info[i].codepoint];
#ifdef VKVG_USE_HARFBUZZ
if (cr == NULL)
}
}
-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);
#ifdef VKVG_USE_FREETYPE
FT_Vector advance; /* horizontal or vertical advance */
#else
- vec2 advance;
+ vec2 advance;
#endif
} _char_ref;
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;
/* 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*/
+ 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 */
+ unsigned char* fontBuffer; /* stb_truetype in memory buffer */
long fontBufSize; /* */
- char *fontFile; /* Font file full path*/
+ char* fontFile; /* Font file full path*/
#ifndef VKVG_USE_FREETYPE
stbtt_fontinfo stbInfo; /* stb_truetype structure */
int ascent; /* unscalled stb font metrics */
int lineGap;
#endif
uint32_t sizeCount; /* available font size loaded */
- _vkvg_font_t *sizes; /* loaded font size array */
+ _vkvg_font_t* sizes; /* loaded font size array */
} _vkvg_font_identity_t;
// Font cache global structure, entry point for all font related operations.
#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 */
+ 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 */
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 */
+ 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 */
+ _vkvg_font_identity_t* fonts; /* Loaded fonts structure array */
int32_t fontsCount; /* Loaded fonts array count*/
} _font_cache_t;
// 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 */
+ _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*/
+ 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;
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);
+_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);
+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);
+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);
+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);
+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
static vkvg_status_t _vkvg_status_invalid_dev_ci = VKVG_STATUS_INVALID_DEVICE_CREATE_INFO;
static vkvg_status_t _vkvg_status_device_error = VKVG_STATUS_DEVICE_ERROR;
static vkvg_status_t _vkvg_status_invalid_surface = VKVG_STATUS_INVALID_SURFACE;
-
#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) {
+static void _vkvg_matrix_scalar_multiply(vkvg_matrix_t* matrix, float scalar) {
matrix->xx *= scalar;
matrix->yx *= 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) {
+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;
if (y0)
*y0 = matrix->y0;
}
-static void _vkvg_matrix_compute_adjoint(vkvg_matrix_t *matrix) {
+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_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 _vkvg_matrix_compute_determinant(const vkvg_matrix_t* matrix) {
float a, b, c, d;
a = matrix->xx;
return a * d - b * c;
}
-vkvg_status_t vkvg_matrix_invert(vkvg_matrix_t *matrix) {
+vkvg_status_t vkvg_matrix_invert(vkvg_matrix_t* matrix) {
float det;
/* Simple scaling|translation matrices are quite common... */
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_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) {
+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->y0 = y0;
}
-void vkvg_matrix_init_translate(vkvg_matrix_t *matrix, float tx, float ty) {
+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_rotate(vkvg_matrix_t *matrix, float radians) {
+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;
vkvg_matrix_init(matrix, c, s, -s, c, 0, 0);
}
-void vkvg_matrix_translate(vkvg_matrix_t *matrix, float tx, float ty) {
+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_multiply(matrix, &tmp, matrix);
}
-void vkvg_matrix_scale(vkvg_matrix_t *matrix, float sx, float sy) {
+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_multiply(matrix, &tmp, matrix);
}
-void vkvg_matrix_rotate(vkvg_matrix_t *matrix, float radians) {
+void vkvg_matrix_rotate(vkvg_matrix_t* matrix, float radians) {
vkvg_matrix_t tmp;
vkvg_matrix_init_rotate(&tmp, radians);
vkvg_matrix_multiply(matrix, &tmp, matrix);
}
-void vkvg_matrix_multiply(vkvg_matrix_t *result, const vkvg_matrix_t *a, const vkvg_matrix_t *b) {
+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;
*result = r;
}
-void vkvg_matrix_transform_distance(const vkvg_matrix_t *matrix, float *dx, float *dy) {
+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);
*dx = new_x;
*dy = new_y;
}
-void vkvg_matrix_transform_point(const vkvg_matrix_t *matrix, float *x, float *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;
}
-void vkvg_matrix_get_scale(const vkvg_matrix_t *matrix, float *sx, float *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;*/
LOG(VKVG_LOG_ERR, "CREATE Pattern failed, invalid surface\n");
return (VkvgPattern)&_vkvg_status_null_pointer;
}
- VkvgPattern pat = (vkvg_pattern_t *)calloc(1, sizeof(vkvg_pattern_t));
+ VkvgPattern pat = (vkvg_pattern_t*)calloc(1, sizeof(vkvg_pattern_t));
if (!pat) {
LOG(VKVG_LOG_ERR, "CREATE Pattern failed, no memory\n");
return (VkvgPattern)&_vkvg_status_null_pointer;
return pat;
}
-vkvg_status_t vkvg_pattern_get_linear_points(VkvgPattern pat, float *x0, float *y0, float *x1, float *y1) {
+vkvg_status_t vkvg_pattern_get_linear_points(VkvgPattern pat, float* x0, float* y0, float* x1, float* y1) {
if (vkvg_pattern_status(pat))
return vkvg_pattern_status(pat);
if (pat->type != VKVG_PATTERN_TYPE_LINEAR)
return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
- vkvg_gradient_t *grad = (vkvg_gradient_t *)pat->data;
+ vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data;
*x0 = grad->cp[0].x;
*y0 = grad->cp[0].y;
if (pat->type != VKVG_PATTERN_TYPE_LINEAR)
return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
- vkvg_gradient_t *grad = (vkvg_gradient_t *)pat->data;
+ 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));
+ VkvgPattern pat = (vkvg_pattern_t*)calloc(1, sizeof(vkvg_pattern_t));
if (!pat) {
LOG(VKVG_LOG_ERR, "CREATE Pattern failed, no memory\n");
return (VkvgPattern)&_vkvg_status_null_pointer;
pat->type = VKVG_PATTERN_TYPE_LINEAR;
pat->extend = VKVG_EXTEND_NONE;
- pat->data = (void *)calloc(1, sizeof(vkvg_gradient_t));
+ pat->data = (void*)calloc(1, sizeof(vkvg_gradient_t));
if (pat->data) {
vkvg_pattern_edit_linear(pat, x0, y0, x1, y1);
if (pat->type != VKVG_PATTERN_TYPE_RADIAL)
return VKVG_STATUS_PATTERN_TYPE_MISMATCH;
- vkvg_gradient_t *grad = (vkvg_gradient_t *)pat->data;
+ vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data;
vec2 c0 = {cx0, cy0};
vec2 c1 = {cx1, cy1};
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));
+ VkvgPattern pat = (vkvg_pattern_t*)calloc(1, sizeof(vkvg_pattern_t));
if (!pat) {
LOG(VKVG_LOG_ERR, "CREATE Pattern failed, no memory\n");
return (VkvgPattern)&_vkvg_status_null_pointer;
pat->type = VKVG_PATTERN_TYPE_RADIAL;
pat->extend = VKVG_EXTEND_NONE;
- pat->data = (void *)calloc(1, sizeof(vkvg_gradient_t));
+ pat->data = (void*)calloc(1, sizeof(vkvg_gradient_t));
if (pat->data) {
vkvg_pattern_edit_radial(pat, cx0, cy0, radius0, cx1, cy1, radius1);
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;
+ vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data;
#ifdef VKVG_PREMULT_ALPHA
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;
#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
return (vkvg_pattern_type_t)0;
return pat->type;
}
-vkvg_status_t vkvg_pattern_get_color_stop_count(VkvgPattern pat, uint32_t *count) {
+vkvg_status_t vkvg_pattern_get_color_stop_count(VkvgPattern pat, uint32_t* count) {
if (vkvg_pattern_status(pat))
return vkvg_pattern_status(pat);
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;
+ 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) {
+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 (vkvg_pattern_status(pat))
return vkvg_pattern_status(pat);
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;
+ 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
*a = c.a;
return VKVG_STATUS_SUCCESS;
}
-void vkvg_pattern_set_matrix(VkvgPattern pat, const vkvg_matrix_t *matrix) {
+void vkvg_pattern_set_matrix(VkvgPattern pat, const vkvg_matrix_t* matrix) {
if (vkvg_pattern_status(pat))
return;
pat->matrix = *matrix;
pat->hasMatrix = true;
}
-void vkvg_pattern_get_matrix(VkvgPattern pat, vkvg_matrix_t *matrix) {
+void vkvg_pattern_get_matrix(VkvgPattern pat, vkvg_matrix_t* matrix) {
if (vkvg_pattern_status(pat))
return;
if (pat->hasMatrix)
vkvg_filter_t filter;
vkvg_matrix_t matrix;
bool hasMatrix;
- void *data;
+ void* data;
} vkvg_pattern_t;
typedef struct _vkvg_gradient_t {
surf->status = VKVG_STATUS_SUCCESS;
return surf;
}
-VkvgSurface vkvg_surface_create_for_VkhImage(VkvgDevice dev, void *vkhImg) {
+VkvgSurface vkvg_surface_create_for_VkhImage(VkvgDevice dev, void* vkhImg) {
VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT);
if (surf->status)
return surf;
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 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;
surf->status = VKVG_STATUS_SUCCESS;
return surf;
}
-VkvgSurface vkvg_surface_create_from_image(VkvgDevice dev, const char *filePath) {
+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
+ 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)&_vkvg_status_null_pointer;
return surf->height;
}
-vkvg_status_t vkvg_surface_write_to_png(VkvgSurface surf, const char *path) {
+vkvg_status_t vkvg_surface_write_to_png(VkvgSurface surf, const char* path) {
if (vkvg_surface_status(surf)) {
LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_png failed, invalid status: %d\n", vkvg_surface_status(surf));
return VKVG_STATUS_INVALID_STATUS;
}
if (vkvg_device_status(surf->dev)) {
- LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_png failed, invalid device status: %d\n", vkvg_device_status(surf->dev));
+ LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_png failed, invalid device status: %d\n",
+ vkvg_device_status(surf->dev));
return VKVG_STATUS_INVALID_STATUS;
}
if (surf->dev->pngStagFormat == VK_FORMAT_UNDEFINED) {
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_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_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_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
VkImageBlit blit = {
.srcSubresource = imgSubResLayers,
.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);
+ 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);
uint64_t stride = vkh_image_get_stride(stagImgLinear);
#ifdef VKVG_PREMULT_ALPHA
- //unpremult alpha for saving on disk.
- for(int y = 0; y < surf->height; y++) {
- for(int x = 0; x < surf->width; x++) {
- unsigned char* p = img + y * stride + x * 4;
- double alpha = (double)p[3] / 255.f;
- p[0] = (unsigned char)((double)p[0] / alpha);
- p[1] = (unsigned char)((double)p[1] / alpha);
- p[2] = (unsigned char)((double)p[2] / alpha);
+ // unpremult alpha for saving on disk.
+ for (int y = 0; y < surf->height; y++) {
+ for (int x = 0; x < surf->width; x++) {
+ unsigned char* p = img + y * stride + x * 4;
+ double alpha = (double)p[3] / 255.f;
+ p[0] = (unsigned char)((double)p[0] / alpha);
+ p[1] = (unsigned char)((double)p[1] / alpha);
+ p[2] = (unsigned char)((double)p[2] / alpha);
}
}
#endif
return VKVG_STATUS_SUCCESS;
}
-vkvg_status_t vkvg_surface_write_to_memory(VkvgSurface surf, unsigned char *const bitmap) {
+vkvg_status_t vkvg_surface_write_to_memory(VkvgSurface surf, unsigned char* const bitmap) {
if (vkvg_surface_status(surf)) {
LOG(VKVG_LOG_ERR, "vkvg_surface_write_to_memory failed, invalid status: %d\n", vkvg_surface_status(surf));
return VKVG_STATUS_INVALID_STATUS;
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_COLOR_ATTACHMENT_OUTPUT_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_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
VkImageBlit blit = {
.srcSubresource = imgSubResLayers,
uint64_t stride = vkh_image_get_stride(stagImg);
uint32_t dest_stride = surf->width * 4;
- unsigned char *img = vkh_image_map(stagImg);
+ unsigned char* img = vkh_image_map(stagImg);
#ifdef VKVG_PREMULT_ALPHA
- //unpremult alpha for saving on disk.
- for(int y = 0; y < surf->height; y++) {
- for(int x = 0; x < surf->width; x++) {
- unsigned char* p = img + y * stride + x * 4;
- double alpha = (double)p[3] / 255.f;
- p[0] = (unsigned char)((double)p[0] / alpha);
- p[1] = (unsigned char)((double)p[1] / alpha);
- p[2] = (unsigned char)((double)p[2] / alpha);
+ // unpremult alpha for saving on disk.
+ for (int y = 0; y < surf->height; y++) {
+ for (int x = 0; x < surf->width; x++) {
+ unsigned char* p = img + y * stride + x * 4;
+ double alpha = (double)p[3] / 255.f;
+ p[0] = (unsigned char)((double)p[0] / alpha);
+ p[1] = (unsigned char)((double)p[1] / alpha);
+ p[2] = (unsigned char)((double)p[2] / alpha);
}
}
#endif
- unsigned char *row = (unsigned char *)bitmap;
+ unsigned char* row = (unsigned char*)bitmap;
for (uint32_t y = 0; y < surf->height; y++) {
memcpy(row, img, dest_stride);
row += dest_stride;
return (VkvgSurface)&_vkvg_status_device_error;
}
- VkvgSurface surf = (vkvg_surface *)calloc(1, sizeof(vkvg_surface));
+ VkvgSurface surf = (vkvg_surface*)calloc(1, sizeof(vkvg_surface));
if (!surf) {
LOG(VKVG_LOG_ERR, "CREATE Surface failed, no memory\n");
return (VkvgSurface)&_vkvg_status_no_memory;
}
surf->references = 1;
- surf->dev = dev;
- surf->format = format;
+ surf->dev = dev;
+ surf->format = format;
if (dev->threadAware)
mtx_init(&surf->mutex, mtx_plain);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
PERFORM_TEST(test_name, argc, argv);
return 0;
}
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(sizes, argc, argv);
PERFORM_TEST(scaled_up, argc, argv);
// 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) {
+static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action == GLFW_RELEASE)
return;
switch (key) {
#endif
}
}
-static void mouse_move_callback(GLFWwindow *window, double x, double y) {
+static void mouse_move_callback(GLFWwindow* window, double x, double y) {
if (mouseDown) {
if (hoverPt < 0)
return;
hoverPt = -1;
}
}
-static void scroll_callback(GLFWwindow *window, double x, double y) {
+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) {
+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 = false;
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
_parse_args(argc, argv);
VkEngine e;
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(fill_and_stroke, argc, argv);
PERFORM_TEST(sizes, argc, argv);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(clip_transformed_ec, argc, argv);
PERFORM_TEST(clipped_paint_ec, argc, argv);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(test, argc, argv);
char type;
union {
unsigned int color;
- NSVGgradient *gradient;
+ NSVGgradient* gradient;
};
} NSVGpaint;
typedef struct NSVGpath {
- float *pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
+ 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.
+ struct NSVGpath* next; // Pointer to next path, or NULL if last element.
} NSVGpath;
typedef struct NSVGshape {
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.
+ 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.
+ 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
}
#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) {
+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++;
(*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];
+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;
+ char* name;
int start = 0;
int end = 0;
char quote;
// Get attribs
while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS - 3) {
- char *name = NULL;
- char *value = NULL;
+ char* name = NULL;
+ char* value = NULL;
// Skip white space before the attrib name
while (*s && nsvg__isspace(*s))
(*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 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) {
char units;
float xform[6];
int nstops;
- NSVGgradientStop *stops;
- struct NSVGgradientData *next;
+ NSVGgradientStop* stops;
+ struct NSVGgradientData* next;
} NSVGgradientData;
typedef struct NSVGattrib {
typedef struct NSVGparser {
NSVGattrib attr[NSVG_MAX_ATTR];
int attrHead;
- float *pts;
+ float* pts;
int npts;
int cpts;
- NSVGpath *plist;
- NSVGimage *image;
- NSVGgradientData *gradients;
- NSVGshape *shapesTail;
+ NSVGpath* plist;
+ NSVGimage* image;
+ NSVGgradientData* gradients;
+ NSVGshape* shapesTail;
float viewMinx, viewMiny, viewWidth, viewHeight;
int alignX, alignY, alignType;
float dpi;
char defsFlag;
} NSVGparser;
-static void nsvg__xformIdentity(float *t) {
+static void nsvg__xformIdentity(float* t) {
t[0] = 1.0f;
t[1] = 0.0f;
t[2] = 0.0f;
t[5] = 0.0f;
}
-static void nsvg__xformSetTranslation(float *t, float tx, float ty) {
+static void nsvg__xformSetTranslation(float* t, float tx, float ty) {
t[0] = 1.0f;
t[1] = 0.0f;
t[2] = 0.0f;
t[5] = ty;
}
-static void nsvg__xformSetScale(float *t, float sx, float sy) {
+static void nsvg__xformSetScale(float* t, float sx, float sy) {
t[0] = sx;
t[1] = 0.0f;
t[2] = 0.0f;
t[5] = 0.0f;
}
-static void nsvg__xformSetSkewX(float *t, float a) {
+static void nsvg__xformSetSkewX(float* t, float a) {
t[0] = 1.0f;
t[1] = 0.0f;
t[2] = tanf(a);
t[5] = 0.0f;
}
-static void nsvg__xformSetSkewY(float *t, float a) {
+static void nsvg__xformSetSkewY(float* t, float a) {
t[0] = 1.0f;
t[1] = tanf(a);
t[2] = 0.0f;
t[5] = 0.0f;
}
-static void nsvg__xformSetRotation(float *t, float a) {
+static void nsvg__xformSetRotation(float* t, float a) {
float cs = cosf(a), sn = sinf(a);
t[0] = cs;
t[1] = sn;
t[5] = 0.0f;
}
-static void nsvg__xformMultiply(float *t, float *s) {
+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[4] = t4;
}
-static void nsvg__xformInverse(float *inv, float *t) {
+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);
inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
}
-static void nsvg__xformPremultiply(float *t, float *s) {
+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) {
+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) {
+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) {
+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];
}
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) {
+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];
+ 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]);
}
}
-static NSVGparser *nsvg__createParser() {
- NSVGparser *p;
- p = (NSVGparser *)malloc(sizeof(NSVGparser));
+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));
+ p->image = (NSVGimage*)malloc(sizeof(NSVGimage));
if (p->image == NULL)
goto error;
memset(p->image, 0, sizeof(NSVGimage));
return NULL;
}
-static void nsvg__deletePaths(NSVGpath *path) {
+static void nsvg__deletePaths(NSVGpath* path) {
while (path) {
- NSVGpath *next = path->next;
+ NSVGpath* next = path->next;
if (path->pts != NULL)
free(path->pts);
free(path);
}
}
-static void nsvg__deletePaint(NSVGpaint *paint) {
+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__deleteGradientData(NSVGgradientData *grad) {
- NSVGgradientData *next;
+static void nsvg__deleteGradientData(NSVGgradientData* grad) {
+ NSVGgradientData* next;
while (grad != NULL) {
next = grad->next;
free(grad->stops);
}
}
-static void nsvg__deleteParser(NSVGparser *p) {
+static void nsvg__deleteParser(NSVGparser* p) {
if (p != NULL) {
nsvg__deletePaths(p->plist);
nsvg__deleteGradientData(p->gradients);
}
}
-static void nsvg__resetPath(NSVGparser *p) { p->npts = 0; }
+static void nsvg__resetPath(NSVGparser* p) { p->npts = 0; }
-static void nsvg__addPoint(NSVGparser *p, float x, float y) {
+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));
+ p->pts = (float*)realloc(p->pts, p->cpts * 2 * sizeof(float));
if (!p->pts)
return;
}
p->npts++;
}
-static void nsvg__moveTo(NSVGparser *p, float x, float y) {
+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;
}
}
-static void nsvg__lineTo(NSVGparser *p, float x, float 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];
}
}
-static void nsvg__cubicBezTo(NSVGparser *p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float 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 NSVGattrib* nsvg__getAttr(NSVGparser* p) { return &p->attr[p->attrHead]; }
-static void nsvg__pushAttr(NSVGparser *p) {
+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) {
+static void nsvg__popAttr(NSVGparser* p) {
if (p->attrHead > 0)
p->attrHead--;
}
-static float nsvg__actualOrigX(NSVGparser *p) { return p->viewMinx; }
+static float nsvg__actualOrigX(NSVGparser* p) { return p->viewMinx; }
-static float nsvg__actualOrigY(NSVGparser *p) { return p->viewMiny; }
+static float nsvg__actualOrigY(NSVGparser* p) { return p->viewMiny; }
-static float nsvg__actualWidth(NSVGparser *p) { return p->viewWidth; }
+static float nsvg__actualWidth(NSVGparser* p) { return p->viewWidth; }
-static float nsvg__actualHeight(NSVGparser *p) { return p->viewHeight; }
+static float nsvg__actualHeight(NSVGparser* p) { return p->viewHeight; }
-static float nsvg__actualLength(NSVGparser *p) {
+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);
+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;
return c.value;
}
-static NSVGgradientData *nsvg__findGradientData(NSVGparser *p, const char *id) {
- NSVGgradientData *grad = p->gradients;
+static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id) {
+ NSVGgradientData* grad = p->gradients;
while (grad) {
if (strcmp(grad->id, id) == 0)
return grad;
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;
+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;
if (stops == NULL)
return NULL;
- grad = (NSVGgradient *)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop) * (nstops - 1));
+ grad = (NSVGgradient*)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop) * (nstops - 1));
if (grad == NULL)
return NULL;
return grad;
}
-static float nsvg__getAverageScale(float *t) {
+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;
+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) {
}
}
-static void nsvg__addShape(NSVGparser *p) {
- NSVGattrib *attr = nsvg__getAttr(p);
+static void nsvg__addShape(NSVGparser* p) {
+ NSVGattrib* attr = nsvg__getAttr(p);
float scale = 1.0f;
- NSVGshape *shape;
- NSVGpath *path;
+ NSVGshape* shape;
+ NSVGpath* path;
int i;
if (p->plist == NULL)
return;
- shape = (NSVGshape *)malloc(sizeof(NSVGshape));
+ shape = (NSVGshape*)malloc(sizeof(NSVGshape));
if (shape == NULL)
goto error;
memset(shape, 0, sizeof(NSVGshape));
free(shape);
}
-static void nsvg__addPath(NSVGparser *p, char closed) {
- NSVGattrib *attr = nsvg__getAttr(p);
- NSVGpath *path = NULL;
+static void nsvg__addPath(NSVGparser* p, char closed) {
+ NSVGattrib* attr = nsvg__getAttr(p);
+ NSVGpath* path = NULL;
float bounds[4];
- float *curve;
+ float* curve;
int i;
if (p->npts < 4)
if (closed)
nsvg__lineTo(p, p->pts[0], p->pts[1]);
- path = (NSVGpath *)malloc(sizeof(NSVGpath));
+ path = (NSVGpath*)malloc(sizeof(NSVGpath));
if (path == NULL)
goto error;
memset(path, 0, sizeof(NSVGpath));
- path->pts = (float *)malloc(p->npts * 2 * sizeof(float));
+ path->pts = (float*)malloc(p->npts * 2 * sizeof(float));
if (path->pts == NULL)
goto error;
path->closed = closed;
}
// 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;
+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;
return res * sign;
}
-static const char *nsvg__parseNumber(const char *s, char *it, const int size) {
+static const char* nsvg__parseNumber(const char* s, char* it, const int size) {
const int last = size - 1;
int i = 0;
return s;
}
-static const char *nsvg__getNextPathItem(const char *s, char *it) {
+static const char* nsvg__getNextPathItem(const char* s, char* it) {
it[0] = '\0';
// Skip white spaces and commas
while (*s && (nsvg__isspace(*s) || *s == ','))
return s;
}
-static unsigned int nsvg__parseColorHex(const char *str) {
+static unsigned int nsvg__parseColorHex(const char* str) {
unsigned int c = 0, r = 0, g = 0, b = 0;
int n = 0;
str++; // skip #
return NSVG_RGB(r, g, b);
}
-static unsigned int nsvg__parseColorRGB(const char *str) {
+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);
}
typedef struct NSVGNamedColor {
- const char *name;
+ const char* name;
unsigned int color;
} NSVGNamedColor;
#endif
};
-static unsigned int nsvg__parseColorName(const char *str) {
+static unsigned int nsvg__parseColorName(const char* str) {
int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);
for (i = 0; i < ncolors; i++) {
return NSVG_RGB(128, 128, 128);
}
-static unsigned int nsvg__parseColor(const char *str) {
+static unsigned int nsvg__parseColor(const char* str) {
size_t len = 0;
while (*str == ' ')
++str;
return nsvg__parseColorName(str);
}
-static float nsvg__parseOpacity(const char *str) {
+static float nsvg__parseOpacity(const char* str) {
float val = 0;
sscanf(str, "%f", &val);
if (val < 0.0f)
return val;
}
-static float nsvg__parseMiterLimit(const char *str) {
+static float nsvg__parseMiterLimit(const char* str) {
float val = 0;
sscanf(str, "%f", &val);
if (val < 0.0f)
return val;
}
-static int nsvg__parseUnits(const char *units) {
+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_USER;
}
-static NSVGcoordinate nsvg__parseCoordinateRaw(const char *str) {
+static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str) {
NSVGcoordinate coord = {0, NSVG_UNITS_USER};
char units[32] = "";
sscanf(str, "%f%31s", &coord.value, units);
return coord;
}
-static float nsvg__parseCoordinate(NSVGparser *p, const char *str, float orig, float length) {
+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;
+static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na) {
+ const char* end;
+ const char* ptr;
char it[64];
*na = 0;
return (int)(end - str);
}
-static int nsvg__parseMatrix(float *xform, const char *str) {
+static int nsvg__parseMatrix(float* xform, const char* str) {
float t[6];
int na = 0;
int len = nsvg__parseTransformArgs(str, t, 6, &na);
return len;
}
-static int nsvg__parseTranslate(float *xform, const char *str) {
+static int nsvg__parseTranslate(float* xform, const char* str) {
float args[2];
float t[6];
int na = 0;
return len;
}
-static int nsvg__parseScale(float *xform, const char *str) {
+static int nsvg__parseScale(float* xform, const char* str) {
float args[2];
int na = 0;
float t[6];
return len;
}
-static int nsvg__parseSkewX(float *xform, const char *str) {
+static int nsvg__parseSkewX(float* xform, const char* str) {
float args[1];
int na = 0;
float t[6];
return len;
}
-static int nsvg__parseSkewY(float *xform, const char *str) {
+static int nsvg__parseSkewY(float* xform, const char* str) {
float args[1];
int na = 0;
float t[6];
return len;
}
-static int nsvg__parseRotate(float *xform, const char *str) {
+static int nsvg__parseRotate(float* xform, const char* str) {
float args[3];
int na = 0;
float m[6];
return len;
}
-static void nsvg__parseTransform(float *xform, const char *str) {
+static void nsvg__parseTransform(float* xform, const char* str) {
float t[6];
nsvg__xformIdentity(xform);
while (*str) {
}
}
-static void nsvg__parseUrl(char *id, const char *str) {
+static void nsvg__parseUrl(char* id, const char* str) {
int i = 0;
str += 4; // "url(";
if (*str == '#')
id[i] = '\0';
}
-static char nsvg__parseLineCap(const char *str) {
+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_BUTT;
}
-static char nsvg__parseLineJoin(const char *str) {
+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_MITER;
}
-static char nsvg__parseFillRule(const char *str) {
+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_NONZERO;
}
-static const char *nsvg__getNextDashItem(const char *s, char *it) {
+static const char* nsvg__getNextDashItem(const char* s, char* it) {
int n = 0;
it[0] = '\0';
// Skip white spaces and commas
return s;
}
-static int nsvg__parseStrokeDashArray(NSVGparser *p, const char *str, float *strokeDashArray) {
+static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray) {
char item[64];
int count = 0, i;
float sum = 0.0f;
return count;
}
-static void nsvg__parseStyle(NSVGparser *p, const char *str);
+static void nsvg__parseStyle(NSVGparser* p, const char* str);
-static int nsvg__parseAttr(NSVGparser *p, const char *name, const char *value) {
+static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value) {
float xform[6];
- NSVGattrib *attr = nsvg__getAttr(p);
+ NSVGattrib* attr = nsvg__getAttr(p);
if (!attr)
return 0;
return 1;
}
-static int nsvg__parseNameValue(NSVGparser *p, const char *start, const char *end) {
- const char *str;
- const char *val;
+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;
return nsvg__parseAttr(p, name, value);
}
-static void nsvg__parseStyle(NSVGparser *p, const char *str) {
- const char *start;
- const char *end;
+static void nsvg__parseStyle(NSVGparser* p, const char* str) {
+ const char* start;
+ const char* end;
while (*str) {
// Left Trim
}
}
-static void nsvg__parseAttribs(NSVGparser *p, const char **attr) {
+static void nsvg__parseAttribs(NSVGparser* p, const char** attr) {
int i;
for (i = 0; attr[i]; i += 2) {
if (strcmp(attr[i], "style") == 0)
return 0;
}
-static void nsvg__pathMoveTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) {
if (rel) {
*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) {
+static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) {
if (rel) {
*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) {
+static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) {
if (rel)
*cpx += args[0];
else
nsvg__lineTo(p, *cpx, *cpy);
}
-static void nsvg__pathVLineTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel) {
+static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) {
if (rel)
*cpy += args[0];
else
nsvg__lineTo(p, *cpx, *cpy);
}
-static void nsvg__pathCubicBezTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+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;
*cpy = y2;
}
-static void nsvg__pathCubicBezShortTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+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;
*cpy = y2;
}
-static void nsvg__pathQuadBezTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args, int rel) {
+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;
*cpy = y2;
}
-static void nsvg__pathQuadBezShortTo(NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args,
+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;
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) {
+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;
*cpy = y2;
}
-static void nsvg__parsePath(NSVGparser *p, const char **attr) {
- const char *s = NULL;
+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];
+ const char* tmp[4];
char closedFlag;
int i;
char item[64];
nsvg__addShape(p);
}
-static void nsvg__parseRect(NSVGparser *p, const char **attr) {
+static void nsvg__parseRect(NSVGparser* p, const char** attr) {
float x = 0.0f;
float y = 0.0f;
float w = 0.0f;
}
}
-static void nsvg__parseCircle(NSVGparser *p, const char **attr) {
+static void nsvg__parseCircle(NSVGparser* p, const char** attr) {
float cx = 0.0f;
float cy = 0.0f;
float r = 0.0f;
}
}
-static void nsvg__parseEllipse(NSVGparser *p, const char **attr) {
+static void nsvg__parseEllipse(NSVGparser* p, const char** attr) {
float cx = 0.0f;
float cy = 0.0f;
float rx = 0.0f;
}
}
-static void nsvg__parseLine(NSVGparser *p, const char **attr) {
+static void nsvg__parseLine(NSVGparser* p, const char** attr) {
float x1 = 0.0;
float y1 = 0.0;
float x2 = 0.0;
nsvg__addShape(p);
}
-static void nsvg__parsePoly(NSVGparser *p, const char **attr, int closeFlag) {
+static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag) {
int i;
- const char *s;
+ const char* s;
float args[2];
int nargs, npts = 0;
char item[64];
nsvg__addShape(p);
}
-static void nsvg__parseSVG(NSVGparser *p, const char **attr) {
+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])) {
}
}
-static void nsvg__parseGradient(NSVGparser *p, const char **attr, char type) {
+static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type) {
int i;
- NSVGgradientData *grad = (NSVGgradientData *)malloc(sizeof(NSVGgradientData));
+ NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData));
if (grad == NULL)
return;
memset(grad, 0, sizeof(NSVGgradientData));
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];
+ const char* href = attr[i + 1];
strncpy(grad->ref, href + 1, 62);
grad->ref[62] = '\0';
}
p->gradients = grad;
}
-static void nsvg__parseGradientStop(NSVGparser *p, const char **attr) {
- NSVGattrib *curAttr = nsvg__getAttr(p);
- NSVGgradientData *grad;
- NSVGgradientStop *stop;
+static void nsvg__parseGradientStop(NSVGparser* p, const char** attr) {
+ NSVGattrib* curAttr = nsvg__getAttr(p);
+ NSVGgradientData* grad;
+ NSVGgradientStop* stop;
int i, idx;
curAttr->stopOffset = 0;
return;
grad->nstops++;
- grad->stops = (NSVGgradientStop *)realloc(grad->stops, sizeof(NSVGgradientStop) * grad->nstops);
+ grad->stops = (NSVGgradientStop*)realloc(grad->stops, sizeof(NSVGgradientStop) * grad->nstops);
if (grad->stops == NULL)
return;
stop->offset = curAttr->stopOffset;
}
-static void nsvg__startElement(void *ud, const char *el, const char **attr) {
- NSVGparser *p = (NSVGparser *)ud;
+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
}
}
-static void nsvg__endElement(void *ud, const char *el) {
- NSVGparser *p = (NSVGparser *)ud;
+static void nsvg__endElement(void* ud, const char* el) {
+ NSVGparser* p = (NSVGparser*)ud;
if (strcmp(el, "g") == 0) {
nsvg__popAttr(p);
}
}
-static void nsvg__content(void *ud, const char *s) {
+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;
+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 (container - content) * 0.5f;
}
-static void nsvg__scaleGradient(NSVGgradient *grad, float tx, float ty, float sx, float sy) {
+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__xformMultiply(grad->xform, t);
}
-static void nsvg__scaleToViewbox(NSVGparser *p, const char *units) {
- NSVGshape *shape;
- NSVGpath *path;
+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;
+ float* pt;
// Guess image size if not set completely.
nsvg__imageBounds(p, bounds);
}
}
-NSVGimage *nsvgParse(char *input, const char *units, float dpi) {
- NSVGparser *p;
- NSVGimage *ret = 0;
+NSVGimage* nsvgParse(char* input, const char* units, float dpi) {
+ NSVGparser* p;
+ NSVGimage* ret = 0;
p = nsvg__createParser();
if (p == NULL) {
return ret;
}
-NSVGimage *nsvgParseFromFile(const char *filename, const char *units, float dpi) {
- FILE *fp = NULL;
+NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi) {
+ FILE* fp = NULL;
size_t size;
- char *data = NULL;
- NSVGimage *image = NULL;
+ char* data = NULL;
+ NSVGimage* image = NULL;
fp = fopen(filename, "rb");
if (!fp)
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
- data = (char *)malloc(size + 1);
+ data = (char*)malloc(size + 1);
if (data == NULL)
goto error;
if (fread(data, 1, size, fp) != size)
return NULL;
}
-void nsvgDelete(NSVGimage *image) {
+void nsvgDelete(NSVGimage* image) {
NSVGshape *snext, *shape;
if (image == NULL)
return;
#include <string.h>
#if defined(_WIN32) || defined(_WIN64)
-int gettimeofday(struct timeval *tp, void *tzp) {
+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);
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'
+ // 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 threadAware = false;
static VkSampleCountFlags samples = VK_SAMPLE_COUNT_4_BIT;
static VkPhysicalDeviceType preferedPhysicalDeviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
-static vk_engine_t *e;
-static char *saveToPng = NULL;
+static vk_engine_t* e;
+static char* saveToPng = NULL;
-static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action != GLFW_PRESS)
return;
switch (key) {
#endif
}
}
-static void char_callback(GLFWwindow *window, uint32_t c) {}
-static void mouse_move_callback(GLFWwindow *window, double x, double 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) {
+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) {
+static void mouse_button_callback(GLFWwindow* window, int but, int state, int modif) {
if (but != GLFW_MOUSE_BUTTON_1)
return;
if (state == GLFW_TRUE)
}
#ifdef VKVG_TEST_DIRECT_DRAW
-VkvgSurface *surfaces;
+VkvgSurface* surfaces;
#endif
void _print_usage_and_exit() {
printf("\nUsage: test [options]\n\n");
printf("\n");
exit(-1);
}
-void _parse_args(int argc, char *argv[]) {
+void _parse_args(int argc, char* argv[]) {
bool printTestDetailsAndExit = false;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-h\0") == 0)
}
}
typedef struct time_struct {
- double start_time;
- double stop_time;
- double run_time;
- double run_total;
- double min_run_time;
- double max_run_time;
- double *run_time_values;
+ double start_time;
+ double stop_time;
+ double run_time;
+ double run_total;
+ double min_run_time;
+ double max_run_time;
+ double* run_time_values;
uint32_t count;
} time_struct_t;
-time_struct_t time_struct_create (uint32_t iterations) {
- time_struct_t ts = {0};
- ts.run_time_values = (double *)malloc(iterations * sizeof(double));
+time_struct_t time_struct_create(uint32_t iterations) {
+ time_struct_t ts = {0};
+ ts.run_time_values = (double*)malloc(iterations * sizeof(double));
return ts;
}
-void time_struct_destroy (time_struct_t* ts) {
- free(ts->run_time_values);
-}
-void time_struct_start(time_struct_t* ts) {
- ts->start_time = get_tick();
-}
+void time_struct_destroy(time_struct_t* ts) { free(ts->run_time_values); }
+void time_struct_start(time_struct_t* ts) { ts->start_time = get_tick(); }
void time_struct_end(time_struct_t* ts) {
- ts->stop_time = get_tick();
- ts->run_time = ts->stop_time - ts->start_time;
+ ts->stop_time = get_tick();
+ ts->run_time = ts->stop_time - ts->start_time;
ts->run_time_values[ts->count] = ts->run_time;
if (ts->min_run_time < 0)
ts->run_total += ts->run_time;
ts->count++;
}
-void _print_results(const char *testName, int argc, char *argv[], time_struct_t* ts) {
- char *whoami;
+void _print_results(const char* testName, int argc, char* argv[], time_struct_t* ts) {
+ char* whoami;
(whoami = strrchr(argv[0], '/')) ? ++whoami : (whoami = argv[0]);
double avg_run_time = ts->run_total / (double)ts->count;
}
#endif
-void perform_test(void (*testfunc)(void), const char *testName, int argc, char *argv[]) {
+void perform_test(void (*testfunc)(void), const char* testName, int argc, char* argv[]) {
setlocale(LC_ALL, "");
// dumpLayerExts();
_parse_args(argc, argv);
perform_test_onscreen(testfunc, testName, argc, argv);
}
-void perform_test_offscreen(void (*testfunc)(void), const char *testName, int argc, char *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];
+ const char* enabledExts[10];
#ifdef VKVG_USE_RENDERDOC
const uint32_t enabledLayersCount = 2;
- const char *enabledLayers[] = {"VK_LAYER_KHRONOS_validation", "VK_LAYER_RENDERDOC_Capture"};
+ 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 char* enabledLayers[] = {"VK_LAYER_KHRONOS_validation"};
#else
const uint32_t enabledLayersCount = 0;
- const char *enabledLayers[] = {NULL};
+ const char* enabledLayers[] = {NULL};
#endif
#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
enabledExts[enabledExtsCount] = "VK_EXT_debug_utils";
NULL);
#endif
bool deferredResolve = false;
- VkhPhyInfo *phys = vkh_app_get_phyinfos(app, &phyCount, VK_NULL_HANDLE);
+ 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))
VkDeviceCreateInfo device_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.queueCreateInfoCount = qCount,
- .pQueueCreateInfos = (VkDeviceQueueCreateInfo *)&pQueueInfos,
+ .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(app), dev->phy, dev->dev, pi->gQueue, 0};
+ vkvg_device_create_info_t info = {samples, deferredResolve, vkh_app_get_inst(app), dev->phy, dev->dev, pi->gQueue,
+ 0};
device = vkvg_device_create(&info);
// vkvg_device_set_dpy(device, 96, 96);
test_index++;
}
-void perform_test_onscreen(void (*testfunc)(void), const char *testName, int argc, char *argv[]) {
+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
vkvg_device_set_dpy(device, 96, 96);
#ifdef VKVG_TEST_DIRECT_DRAW
- surfaces = (VkvgSurface *)malloc(r->imgCount * sizeof(VkvgSurface));
+ 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);
+ 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
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) {
+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;
#endif
// *sigh* no gettimeofday on Win32/Win64
-int gettimeofday(struct timeval *tp, void *tzp);
+int gettimeofday(struct timeval* tp, void* tzp);
#else
#include <sys/time.h>
#endif
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[]);
+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);
/* Standard, good-to-have defines */
#ifndef NULL
-#define NULL (void *)0
+#define NULL (void*)0
#endif
#ifndef TRUE
#define TRUE 1
#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;
#endif
}
-void mtx_destroy(mtx_t *mtx) {
+void mtx_destroy(mtx_t* mtx) {
#if defined(_TTHREAD_WIN32_)
DeleteCriticalSection(&mtx->mHandle);
#else
#endif
}
-int mtx_lock(mtx_t *mtx) {
+int mtx_lock(mtx_t* mtx) {
#if defined(_TTHREAD_WIN32_)
EnterCriticalSection(&mtx->mHandle);
if (!mtx->mRecursive) {
#endif
}
-int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) {
+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) {
#endif
}
-int mtx_unlock(mtx_t *mtx) {
+int mtx_unlock(mtx_t* mtx) {
#if defined(_TTHREAD_WIN32_)
mtx->mAlreadyLocked = FALSE;
LeaveCriticalSection(&mtx->mHandle);
#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;
#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]);
#endif
}
-int cnd_signal(cnd_t *cond) {
+int cnd_signal(cnd_t* cond) {
#if defined(_TTHREAD_WIN32_)
int haveWaiters;
#endif
}
-int cnd_broadcast(cnd_t *cond) {
+int cnd_broadcast(cnd_t* cond) {
#if defined(_TTHREAD_WIN32_)
int haveWaiters;
}
#if defined(_TTHREAD_WIN32_)
-static int _cnd_timedwait_win32(cnd_t *cond, mtx_t *mtx, DWORD timeout) {
+static int _cnd_timedwait_win32(cnd_t* cond, mtx_t* mtx, DWORD timeout) {
int result, lastWaiter;
/* Increment number of waiters */
}
#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);
#else
#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) {
/** 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. */
+ 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;
+ 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;
+ _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);
+ free((void*)ti);
/* Call the actual client thread function */
res = fun(arg);
#else
pres = malloc(sizeof(int));
if (pres != NULL) {
- *(int *)pres = res;
+ *(int*)pres = res;
}
return pres;
#endif
}
-int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) {
+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));
+ _thread_start_info* ti = (_thread_start_info*)malloc(sizeof(_thread_start_info));
if (ti == NULL) {
return thrd_nomem;
}
/* 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) {
+ if (pthread_create(thr, NULL, _thrd_wrapper_function, (void*)ti) != 0) {
*thr = 0;
}
#endif
#if defined(_TTHREAD_WIN32_)
ExitThread(res);
#else
- void *pres = malloc(sizeof(int));
+ void* pres = malloc(sizeof(int));
if (pres != NULL) {
- *(int *)pres = res;
+ *(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;
*res = dwRes;
}
#elif defined(_TTHREAD_POSIX_)
- void *pres;
+ void* pres;
int ires = 0;
if (pthread_join(thr, &pres) != 0) {
return thrd_error;
}
if (pres != NULL) {
- ires = *(int *)pres;
+ ires = *(int*)pres;
free(pres);
}
if (res != NULL) {
return thrd_success;
}
-int thrd_sleep(const struct timespec *time_point, struct timespec *remaining) {
+int thrd_sleep(const struct timespec* time_point, struct timespec* remaining) {
struct timespec now;
#if defined(_TTHREAD_WIN32_)
DWORD delta;
#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) {
#endif
}
-void *tss_get(tss_t key) {
+void* tss_get(tss_t key) {
#if defined(_TTHREAD_WIN32_)
return TlsGetValue(key);
#else
#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 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);
#define clockid_t _tthread_clockid_t
/* 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);
#define clock_gettime _tthread_clock_gettime
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
* @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);
+int mtx_init(mtx_t* mtx, int type);
/** Release any resources used by the given mutex.
* @param mtx A mutex object.
*/
-void mtx_destroy(mtx_t *mtx);
+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
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
-int mtx_lock(mtx_t *mtx);
+int mtx_lock(mtx_t* mtx);
/** NOT YET IMPLEMENTED.
*/
-int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
+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
* requested is already in use, or @ref thrd_error if the request could not be
* honored.
*/
-int mtx_trylock(mtx_t *mtx);
+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.
*/
-int mtx_unlock(mtx_t *mtx);
+int mtx_unlock(mtx_t* mtx);
/* Condition variable */
#if defined(_TTHREAD_WIN32_)
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.
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
-int cnd_init(cnd_t *cond);
+int cnd_init(cnd_t* cond);
/** Release any resources used by the given condition variable.
* @param cond A condition variable object.
*/
-void cnd_destroy(cnd_t *cond);
+void cnd_destroy(cnd_t* cond);
/** Signal a condition variable.
* Unblocks one of the threads that are blocked on the given condition variable
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
-int cnd_signal(cnd_t *cond);
+int cnd_signal(cnd_t* cond);
/** Broadcast a condition variable.
* Unblocks all of the threads that are blocked on the given condition variable
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
-int cnd_broadcast(cnd_t *cond);
+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
* @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);
+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
* 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);
+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.
* @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);
+typedef int (*thrd_start_t)(void* arg);
/** Create a new thread.
* @param thr Identifier of the newly created thread.
* 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);
+int thrd_create(thrd_t* thr, thrd_start_t func, void* arg);
/** Identify the calling thread.
* @return The identifier of the calling thread.
* @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);
+int thrd_join(thrd_t thr, int* res);
/** Put the calling thread to sleep.
* Suspend execution of the calling thread.
* time.
* @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
*/
-int thrd_sleep(const struct timespec *time_point, struct timespec *remaining);
+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
#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.
*/
-typedef void (*tss_dtor_t)(void *val);
+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
* 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);
+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
* @return The value for the current thread held in the given thread-specific
* storage.
*/
-void *tss_get(tss_t key);
+void* tss_get(tss_t key);
/** Set the value for a thread-specific storage.
* @param key The thread-specific storage identifier.
* @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);
+int tss_set(tss_t key, void* val);
#endif /* _TINYTHREAD_H_ */
enabledExts[enabledExtsCount++] = #ext; \
}
-static void glfw_error_callback(int error, const char *description) {
+static void glfw_error_callback(int error, const char* description) {
fprintf(stderr, "vkengine: GLFW error %d: %s\n", error, description);
}
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, NULL);
- VkLayerProperties *availableLayers = (VkLayerProperties *)malloc(layerCount * sizeof(VkLayerProperties));
+ VkLayerProperties* availableLayers = (VkLayerProperties*)malloc(layerCount * sizeof(VkLayerProperties));
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);
printf("Available Layers:\n");
printf("-----------------\n\n");
free(availableLayers);
}
-bool vkengine_try_get_phyinfo(VkhPhyInfo *phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo *phy) {
+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 false;
}
-bool instance_extension_supported(VkExtensionProperties *instanceExtProps, uint32_t extCount,
- const char *instanceName) {
+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,
+vk_engine_t* vkengine_create(VkPhysicalDeviceType preferedGPU, VkPresentModeKHR presentMode, uint32_t width,
uint32_t height) {
glfwSetErrorCallback(glfw_error_callback);
exit(-1);
}
- const char *enabledLayers[10];
- const char *enabledExts[10];
+ const char* enabledLayers[10];
+ const char* enabledExts[10];
uint32_t enabledExtsCount = 0, enabledLayersCount = 0, phyCount = 0;
vkh_layers_check_init();
vkh_layers_check_release();
uint32_t glfwReqExtsCount = 0;
- const char **gflwExts = glfwGetRequiredInstanceExtensions(&glfwReqExtsCount);
+ const char** gflwExts = glfwGetRequiredInstanceExtensions(&glfwReqExtsCount);
vkvg_get_required_instance_extensions(enabledExts, &enabledExtsCount);
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);
#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);
+ 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);
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) &&
TRY_LOAD_DEVICE_EXT(VK_KHR_swapchain)
VkPhysicalDeviceFeatures enabledFeatures = {0};
- const void *pNext = vkvg_get_device_requirements(&enabledFeatures);
+ const void* pNext = vkvg_get_device_requirements(&enabledFeatures);
VkDeviceCreateInfo device_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.queueCreateInfoCount = qCount,
- .pQueueCreateInfos = (VkDeviceQueueCreateInfo *)&pQueueInfos,
+ .pQueueCreateInfos = (VkDeviceQueueCreateInfo*)&pQueueInfos,
.enabledExtensionCount = enabledExtsCount,
.ppEnabledExtensionNames = enabledExts,
.pEnabledFeatures = &enabledFeatures,
}
}
bool vkengine_should_close(VkEngine e) { return glfwWindowShouldClose(e->window); }
-void vkengine_set_title(VkEngine e, const char *title) { glfwSetWindowTitle(e->window, title); }
+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; }
#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;
+ GLFWwindow* window;
VkhPresenter renderer;
} vk_engine_t;
-vk_engine_t *vkengine_create(VkPhysicalDeviceType preferedGPU, VkPresentModeKHR presentMode, uint32_t width,
+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);
+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);
+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);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(compositing, argc, argv);
PERFORM_TEST(opacity, argc, argv);
#include "test.h"
void create_destroy_multi() {
- VkvgContext *ctxs = (VkvgContext *)malloc(sizeof(VkvgContext) * test_size);
+ 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(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
PERFORM_TEST(create_destroy_multi, argc, argv);
no_test_size = true;
PERFORM_TEST(create_destroy_single, argc, argv);
fill_rule = VKVG_FILL_RULE_EVEN_ODD;
_long_curv();
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(test3, argc, argv);
// return 0;
void path() { _long_path(); }
void curve() { _long_curve(); }
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
dashes_count = 2;
dashes[0] = 0;
dashes[1] = 10;
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(test, argc, argv);
return 0;
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(test, argc, argv);
return 0;
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(test, argc, argv);
return 0;
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(gradient_alpha, argc, argv);
PERFORM_TEST(paint, argc, argv);
vkvg_pattern_destroy(pat);
vkvg_destroy(ctx);
}
-static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action != GLFW_PRESS)
return;
switch (key) {
break;
}
}
-static void mouse_move_callback(GLFWwindow *window, double x, double y) {
+static void mouse_move_callback(GLFWwindow* window, double x, double y) {
if (mouseDown) {
if (hoverPt < 0)
return;
hoverPt = -1;
}
}
-static void scroll_callback(GLFWwindow *window, double x, double y) {
+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) {
+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 = false;
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
_parse_args(argc, argv);
#include "test.h"
-const char *imgPath = TESTS_DATA_ROOT "miroir.jpg";
+const char* imgPath = TESTS_DATA_ROOT "miroir.jpg";
const char* imgPath2 = TESTS_DATA_ROOT "miroir.png";
const char* imgPath3 = TESTS_DATA_ROOT "filled.png";
-const char *imgPath4 = TESTS_DATA_ROOT "miroir2.png";
-const char *imgPath5 = TESTS_DATA_ROOT "miroir2-64.png";
+const char* imgPath4 = TESTS_DATA_ROOT "miroir2.png";
+const char* imgPath5 = TESTS_DATA_ROOT "miroir2-64.png";
-void paint() {
+void paint() {
VkvgContext ctx = vkvg_create(surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
VkvgContext ctx = vkvg_create(surf);
vkvg_clear(ctx);
- vkvg_translate(ctx, 142,142);
+ vkvg_translate(ctx, 142, 142);
vkvg_rotate(ctx, angle);
- vkvg_translate(ctx, -142,-142);
+ vkvg_translate(ctx, -142, -142);
VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath4);
vkvg_set_source_surface(ctx, imgSurf, 100, 100);
void imgTest() {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_line_width(ctx, 1.0); // 设置线宽
- vkvg_set_line_cap(ctx, VKVG_LINE_CAP_ROUND); // 设置线条端点样式
+ vkvg_set_line_width(ctx, 1.0); // 设置线宽
+ vkvg_set_line_cap(ctx, VKVG_LINE_CAP_ROUND); // 设置线条端点样式
vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND); // 设置线条连接样式
VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath3);
}
void imgTest2() {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_line_width(ctx, 10.0); // 设置线宽
- vkvg_set_line_cap(ctx, VKVG_LINE_CAP_ROUND); // 设置线条端点样式
+ vkvg_set_line_width(ctx, 10.0); // 设置线宽
+ vkvg_set_line_cap(ctx, VKVG_LINE_CAP_ROUND); // 设置线条端点样式
vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND); // 设置线条连接样式
VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath3);
vkvg_arc(ctx, arcSize, arcSize, arcSize, 0, 2.f * M_PIF);
vkvg_fill_preserve(ctx);
vkvg_arc(ctx, arcSize, arcSize, arcSize, 0, 2.f * M_PIF);
- vkvg_set_source_rgba(ctx,0.4f,0.4f,0.9f,1);
+ vkvg_set_source_rgba(ctx, 0.4f, 0.4f, 0.9f, 1);
vkvg_stroke(ctx);
void imgTestClipped() {
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_line_width(ctx, 10.0); // 设置线宽
- vkvg_set_line_cap(ctx, VKVG_LINE_CAP_ROUND); // 设置线条端点样式
- vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND); // 设置线条连接样式
+ vkvg_set_line_width(ctx, 10.0); // 设置线宽
+ vkvg_set_line_cap(ctx, VKVG_LINE_CAP_ROUND); // 设置线条端点样式
+ vkvg_set_line_join(ctx, VKVG_LINE_JOIN_ROUND); // 设置线条连接样式
vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD); // 设置线条连接样式
- vkvg_set_source_rgba(ctx,0,0,0,1);
- vkvg_paint(ctx);//black background, or png will be transparent
-
+ vkvg_set_source_rgba(ctx, 0, 0, 0, 1);
+ vkvg_paint(ctx); // black background, or png will be transparent
VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath3);
vkvg_set_source_surface(ctx, imgSurf, 0, 0);
vkvg_destroy(ctx);
}
void imgTest3() {
- VkvgContext ctx = vkvg_create(surf);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ VkvgContext ctx = vkvg_create(surf);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
VkvgSurface imgSurf2 = vkvg_surface_create_from_image(device, imgPath3);
vkvg_set_operator(ctx, VKVG_OPERATOR_OVER);
vkvg_set_source_surface(ctx, imgSurf, 0, 0);
vkvg_paint(ctx);
vkvg_set_operator(ctx, VKVG_OPERATOR_OVER);
- //vkvg_set_source_rgba(ctx, 1.0, 1.0, 1.0, 0.4);
+ // vkvg_set_source_rgba(ctx, 1.0, 1.0, 1.0, 0.4);
vkvg_set_source_surface(ctx, imgSurf2, 40, 40);
vkvg_paint(ctx);
vkvg_surface_destroy(imgSurf);
vkvg_surface_destroy(imgSurf2);
- //vkvg_surface_write_to_png(surface, "imgTest3.png");
+ // vkvg_surface_write_to_png(surface, "imgTest3.png");
- //vkvg_surface_destroy(surface);
+ // vkvg_surface_destroy(surface);
}
-void imgWithAlphaTest0() { //VkvgSurface surface = vkvg_surface_create(device, 800, 600);
+void imgWithAlphaTest0() { // VkvgSurface surface = vkvg_surface_create(device, 800, 600);
- VkvgContext ctx = vkvg_create(surf);
+ VkvgContext ctx = vkvg_create(surf);
VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath3);
vkvg_set_source_surface(ctx, imgSurf, 40, 40);
vkvg_surface_destroy(imgSurf);
}
void imgWithAlphaTest1() {
- VkvgContext ctx = vkvg_create(surf);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ VkvgContext ctx = vkvg_create(surf);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
VkvgSurface imgSurf2 = vkvg_surface_create_from_image(device, imgPath3);
vkvg_set_source_surface(ctx, imgSurf, 0, 0);
vkvg_destroy(ctx);
}
void imgTest4() {
- VkvgContext ctx = vkvg_create(surf);
- VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
+ VkvgContext ctx = vkvg_create(surf);
+ VkvgSurface imgSurf = vkvg_surface_create_from_image(device, imgPath);
VkvgSurface imgSurf2 = vkvg_surface_create_from_image(device, imgPath3);
vkvg_set_operator(ctx, VKVG_OPERATOR_OVER);
float arcSize = 70.f;
- //vkvg_set_operator(ctx, VKVG_OPERATOR_OVER);
- //vkvg_set_source_rgba(ctx, 1.0, 1.0, 1.0, 0.4);
+ // vkvg_set_operator(ctx, VKVG_OPERATOR_OVER);
+ // vkvg_set_source_rgba(ctx, 1.0, 1.0, 1.0, 0.4);
vkvg_set_source_surface(ctx, imgSurf2, 50, 50);
- //vkvg_arc(ctx, arcSize, arcSize, 60.f, 0, 2.f * M_PIF);
- vkvg_rectangle(ctx,50,50,120,120);
+ // vkvg_arc(ctx, arcSize, arcSize, 60.f, 0, 2.f * M_PIF);
+ vkvg_rectangle(ctx, 50, 50, 120, 120);
vkvg_paint(ctx);
vkvg_set_source_rgba(ctx, 1.0f, 0.0f, 0.0f, 0.9f);
vkvg_arc(ctx, 200, 200, 21.f, 0, M_PIF * 2);
vkvg_fill(ctx);
-
-
- //vkvg_set_line_width(ctx, 1);
-
+ // vkvg_set_line_width(ctx, 1);
vkvg_surface_destroy(imgSurf2);
vkvg_surface_destroy(imgSurf);
vkvg_destroy(ctx);
- //vkvg_surface_write_to_png(surf, "imgTest4.png");
+ // vkvg_surface_write_to_png(surf, "imgTest4.png");
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(paint, argc, argv);
PERFORM_TEST(paint_offset, argc, argv);
// 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) {
+static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action == GLFW_RELEASE)
return;
switch (key) {
break;
}
}
-static void mouse_move_callback(GLFWwindow *window, double x, double y) {
+static void mouse_move_callback(GLFWwindow* window, double x, double y) {
if (mouseDown) {
if (hoverPt < 0)
return;
hoverPt = -1;
}
}
-static void scroll_callback(GLFWwindow *window, double x, double y) {
+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) {
+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 = false;
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
_parse_args(argc, argv);
VkEngine e;
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(test, argc, argv);
return 0;
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(test, argc, argv);
PERFORM_TEST(test2, argc, argv);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
struct timeval currentTime;
gettimeofday(¤tTime, NULL);
#define THREAD_COUNT 32
static int finishedThreadCount = 0;
-static mtx_t *pmutex;
+static mtx_t* pmutex;
void drawRandomRect(VkvgContext ctx, float s) {
float w = (float)test_width;
pmutex = NULL;
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
PERFORM_TEST(fixedSizeRects, argc, argv);
return 0;
}
#define THREAD_COUNT 32
static int finishedThreadCount = 0;
-static mtx_t *pmutex;
+static mtx_t* pmutex;
void drawRandomRect(VkvgContext ctx, float s) {
float w = (float)test_width;
pmutex = NULL;
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
PERFORM_TEST(fixedSizeRects, argc, argv);
return 0;
}
#define THREAD_COUNT 16
static int finishedThreadCount = 0;
-static mtx_t *pmutex;
+static mtx_t* pmutex;
int create_surfs() {
for (uint32_t i = 0; i < test_size; i++) {
pmutex = NULL;
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
PERFORM_TEST(fixedSizeRects, argc, argv);
return 0;
}
#define THREAD_COUNT 16
static int finishedThreadCount = 0;
-static mtx_t *pmutex;
+static mtx_t* pmutex;
void drawRandomRect(VkvgContext ctx, float s) {
float w = (float)test_width;
vkvg_surface_destroy(s);
return 0;
}
-void threaded_text(int (*testfunc)(void *)) {
+void threaded_text(int (*testfunc)(void*)) {
mtx_t mutex;
pmutex = &mutex;
}
void single_font_and_size() { threaded_text(_single_font_and_size); }
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
PERFORM_TEST(single_font_and_size, argc, argv);
return 0;
}
#include "vkvg.h"
-int main(int argc, char *argv[]) {
+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);
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(paint, argc, argv);
PERFORM_TEST(paint_with_offset, argc, argv);
vkvg_destroy(ctx);
}
-static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action != GLFW_PRESS)
return;
switch (key) {
refresh = true;
}
static vec2 mousePos;
-static void mouse_move_callback(GLFWwindow *window, double x, double y) {
+static void mouse_move_callback(GLFWwindow* window, double x, double y) {
mousePos = (vec2){x, y};
if (mouseDown) {
if (hoverPt < 0)
hoverPt = -1;
}
}
-static void scroll_callback(GLFWwindow *window, double x, double y) {
+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) {
+static void mouse_button_callback(GLFWwindow* window, int but, int state, int modif) {
if (but != GLFW_MOUSE_BUTTON_1)
return;
if (state == GLFW_TRUE)
refresh = true;
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
_parse_args(argc, argv);
VkEngine e;
#include "test.h"
-float lineWidth = 10.f;
+float lineWidth = 10.f;
static float angle = 0;
-const char *imgPath = "data/miroir.jpg";
+const char* imgPath = "data/miroir.jpg";
VkvgPattern create_grad(VkvgContext ctx) {
VkvgPattern pat = vkvg_pattern_create_linear(0, 0, 200, 0);
vkvg_destroy(ctx);
vkvg_pattern_destroy(pat);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(pat_scale, argc, argv);
PERFORM_TEST(pat_rotate, argc, argv);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
PERFORM_TEST(fixedSizeRects, argc, argv);
return 0;
}
void random_stroke() { _shape_stroke(SHAPE_RANDOM); }
void random_fill_stroke() { _shape_fill_stroke(SHAPE_RANDOM); }
-int main(int argc, char *argv[]) {
+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);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(test, argc, argv);
vkvg_recording_destroy(rec);
}
#endif
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
#if VKVG_RECORDING
PERFORM_TEST(test, argc, argv);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(test, argc, argv);
PERFORM_TEST(test_evenodd, argc, argv);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(test, argc, argv);
return 0;
vkvg_paint(ctx);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(paint, argc, argv);
PERFORM_TEST(paint_with_rotation, argc, argv);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
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);
+ 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(s);
}
-int main(int argc, char *argv[]) {
+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);
#include "vkvg-svg.h"
static float rotation = 0.f;
-static const char *path = TESTS_DATA_ROOT "tiger.svg";
-static const char *svgSubPath = TESTS_DATA_ROOT "checkbox.svg";
+static const char* path = TESTS_DATA_ROOT "tiger.svg";
+static const char* svgSubPath = TESTS_DATA_ROOT "checkbox.svg";
void svg_surface() {
VkvgSurface svgSurf = vkvg_surface_create_from_svg(device, test_width, test_height, path);
vkvg_svg_destroy(svg);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(svg_surface, argc, argv);
vkvg_font_extents_t ft;
// vkvg_set_fill_rule(cr, VKVG_FILL_RULE_NON_ZERO);
- const char *utf8 = "vkvg|Ãp";
+ const char* utf8 = "vkvg|Ãp";
float x, y;
// vkvg_select_font_face (cr, "times");
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
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);
}
-void print_boxed(VkvgContext ctx, const char *text, float penX, float penY, uint32_t size) {
+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_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) {
+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_destroy(ctx);
}
-const char *const fonts[] = {"mono", "droid", "times", "arial", "times:bold"};
+const char* const fonts[] = {"mono", "droid", "times", "arial", "times:bold"};
void random_font_and_size() {
VkvgContext ctx = vkvg_create(surf);
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(simple_text, argc, argv);
PERFORM_TEST(font_file_path, argc, argv);
vkvg_destroy(ctx);
}
-static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action != GLFW_PRESS)
return;
switch (key) {
#endif
}
}
-static void mouse_move_callback(GLFWwindow *window, double x, double 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) {
+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) {
+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 = false;
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
_parse_args(argc, argv);
VkEngine e;
vkvg_destroy(ctx);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
no_test_size = true;
PERFORM_TEST(cairo_tests, argc, argv);
return 0;
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 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;
#endif
int _count_svg_files() {
- struct dirent *de;
+ struct dirent* de;
rewinddir(pCurrentDir);
int i = 0;
while ((de = readdir(pCurrentDir)) != NULL) {
newSvgSurf = vkvg_surface_create(dev, width, height);
VkvgContext ctx = vkvg_create(newSvgSurf);
- struct dirent *de;
+ struct dirent* de;
rewinddir(pCurrentDir);
int i = 0;
while ((de = readdir(pCurrentDir)) != NULL) {
#endif
}
-struct dirent *get_next_svg_file_in_current_directory(bool cycle) {
- struct dirent *de;
+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 get_next_svg_file_in_current_directory(false);
}
-static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action == GLFW_RELEASE)
return;
switch (key) {
break;
}
}
-static void scroll_callback(GLFWwindow *window, double x, double y) {
+static void scroll_callback(GLFWwindow* window, double x, double y) {
if (iconSize == 0)
return;
scrollX -= x * 25;
exit(-1);
}
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
int i = 1;
- char *output = NULL;
+ char* output = NULL;
while (i < argc) {
int argLen = strlen(argv[i]);