Skip to content

Commit

Permalink
Add "no_rive_jpeg" and "no_rive_png" build options
Browse files Browse the repository at this point in the history
Some platforms have native support for jpeg and png but sill need webp support.

Diffs=
5df5be1940 Add "no_rive_jpeg" and "no_rive_png" build options (#8702)

Co-authored-by: Chris Dalton <99840794+csmartdalton@users.noreply.github.com>
  • Loading branch information
csmartdalton and csmartdalton committed Dec 7, 2024
1 parent 422c878 commit acfc0e6
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 52 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
d7794cb55668b1a3badcb5aa6b57f922830c95ad
5df5be19407d970646e7a2192b0f6f0790d91096
22 changes: 22 additions & 0 deletions decoders/include/rive/decoders/bitmap_decoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define _RIVE_BITMAP_DECODER_HPP_

#include <memory>
#include <vector>

/// Bitmap will always take ownership of the bytes it is constructed with.
class Bitmap
Expand Down Expand Up @@ -46,6 +47,27 @@ class Bitmap
size_t byteSize(PixelFormat format) const;
size_t bytesPerPixel(PixelFormat format) const;

enum class ImageType
{
png,
jpeg,
webp,
};

using BitmapDecoder = std::unique_ptr<Bitmap> (*)(const uint8_t bytes[],
size_t byteCount);

struct ImageFormat
{
const char* name;
ImageType type;
std::vector<uint8_t> fingerprint;
BitmapDecoder decodeImage;
};

static const ImageFormat* RecognizeImageFormat(const uint8_t bytes[],
size_t byteCount);

static std::unique_ptr<Bitmap> decode(const uint8_t bytes[],
size_t byteCount);

Expand Down
28 changes: 25 additions & 3 deletions decoders/premake5_v2.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,19 @@ dofile(rive .. '/dependencies/premake5_libpng_v2.lua')
dofile(rive .. '/dependencies/premake5_libjpeg_v2.lua')
dofile(rive .. '/dependencies/premake5_libwebp_v2.lua')

newoption({
trigger = 'no_rive_png',
description = 'don\'t build png (or zlib) support into the rive_decoders library (built-in png decoding will fail)',
})

newoption({
trigger = 'no_rive_jpeg',
description = 'don\'t build jpeg support into the rive_decoders library (built-in jpeg decoding will fail)',
})

project('rive_decoders')
do
dependson('libpng', 'zlib', 'libjpeg', 'libwebp')
dependson('libwebp')
kind('StaticLib')
flags({ 'FatalCompileWarnings' })

Expand All @@ -38,8 +48,20 @@ do
files({
'src/bitmap_decoder_thirdparty.cpp',
'src/decode_webp.cpp',
'src/decode_jpeg.cpp',
'src/decode_png.cpp',
})
end

filter({ 'system:not macosx', 'system:not ios', 'options:not no_rive_png' })
do
dependson('zlib', 'libpng')
defines({ 'RIVE_PNG' })
files({ 'src/decode_png.cpp' })
end

filter({ 'system:not macosx', 'system:not ios', 'options:not no_rive_jpeg' })
do
dependson('libjpeg')
defines({ 'RIVE_JPEG' })
files({ 'src/decode_jpeg.cpp' })
end
end
82 changes: 50 additions & 32 deletions decoders/src/bitmap_decoder_thirdparty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,57 @@
*/

#include "rive/decoders/bitmap_decoder.hpp"
#include "rive/rive_types.hpp"
#include <stdio.h>
#include <string.h>
#include <vector>

#ifdef RIVE_PNG
std::unique_ptr<Bitmap> DecodePng(const uint8_t bytes[], size_t byteCount);
#endif
#ifdef RIVE_JPEG
std::unique_ptr<Bitmap> DecodeJpeg(const uint8_t bytes[], size_t byteCount);
#endif
std::unique_ptr<Bitmap> DecodeWebP(const uint8_t bytes[], size_t byteCount);

using BitmapDecoder = std::unique_ptr<Bitmap> (*)(const uint8_t bytes[],
size_t byteCount);
struct ImageFormat
{
const char* name;
std::vector<uint8_t> fingerprint;
BitmapDecoder decodeImage;
static Bitmap::ImageFormat _formats[] = {
{
"png",
Bitmap::ImageType::png,
{0x89, 0x50, 0x4E, 0x47},
#ifdef RIVE_PNG
DecodePng,
#else
nullptr,
#endif
},
{
"jpeg",
Bitmap::ImageType::jpeg,
{0xFF, 0xD8, 0xFF},
#ifdef RIVE_JPEG
DecodeJpeg,
#else
nullptr,
#endif
},
{
"webp",
Bitmap::ImageType::webp,
{0x52, 0x49, 0x46},
DecodeWebP,
},
};

std::unique_ptr<Bitmap> Bitmap::decode(const uint8_t bytes[], size_t byteCount)
const Bitmap::ImageFormat* Bitmap::RecognizeImageFormat(const uint8_t bytes[],
size_t byteCount)
{
static ImageFormat decoders[] = {
{
"png",
{0x89, 0x50, 0x4E, 0x47},
DecodePng,
},
{
"jpeg",
{0xFF, 0xD8, 0xFF},
DecodeJpeg,
},
{
"webp",
{0x52, 0x49, 0x46},
DecodeWebP,
},
};

for (auto recognizer : decoders)
for (const ImageFormat& format : _formats)
{
auto& fingerprint = recognizer.fingerprint;
auto& fingerprint = format.fingerprint;

// Immediately discard decoders with fingerprints that are longer than
// the file buffer.
if (recognizer.fingerprint.size() > byteCount)
if (format.fingerprint.size() > byteCount)
{
continue;
}
Expand All @@ -59,12 +65,24 @@ std::unique_ptr<Bitmap> Bitmap::decode(const uint8_t bytes[], size_t byteCount)
continue;
}

auto bitmap = recognizer.decodeImage(bytes, byteCount);
return &format;
}
return nullptr;
}

std::unique_ptr<Bitmap> Bitmap::decode(const uint8_t bytes[], size_t byteCount)
{
const ImageFormat* format = RecognizeImageFormat(bytes, byteCount);
if (format != nullptr)
{
auto bitmap = format->decodeImage != nullptr
? format->decodeImage(bytes, byteCount)
: nullptr;
if (!bitmap)
{
fprintf(stderr,
"Bitmap::decode - failed to decode a %s.\n",
recognizer.name);
format->name);
}
return bitmap;
}
Expand Down
12 changes: 9 additions & 3 deletions renderer/premake5.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,20 @@ do
'rive',
'rive_pls_renderer',
'rive_decoders',
'libpng',
'zlib',
'libjpeg',
'libwebp',
'rive_harfbuzz',
'rive_sheenbidi',
'rive_yoga',
})
filter({ 'options:not no_rive_png' })
do
links({ 'zlib', 'libpng' })
end
filter({ 'options:not no_rive_jpeg' })
do
links({ 'libjpeg' })
end
filter({})

if _OPTIONS['with_vulkan'] then
dofile('rive_vk_bootstrap/bootstrap_project.lua')
Expand Down
5 changes: 4 additions & 1 deletion tests/gm/image_lod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ class ImageLODGM : public GM
rive::AABB r = {0, 0, 442, 412};
renderer->save();
auto img = LoadImage(assets::batdude_png());
assert(img != nullptr);
if (img == nullptr)
{
return;
}

renderer->translate(10, 10);

Expand Down
4 changes: 4 additions & 0 deletions tests/gm/lots_of_squares.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@ class LotsOfImagesGM : public LotsOfSquaresGM
imagePixels.data(),
PNGCompression::fast_rle);
image = factory->decodeImage(rive::Span<uint8_t>(encodedData));
if (image == nullptr)
{
return;
}
}

AutoRestore ar(renderer, /*doSave=*/true);
Expand Down
23 changes: 11 additions & 12 deletions tests/gm/mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,6 @@ class MeshGM : public GM
void onDraw(rive::Renderer* ren) override
{
auto img = LoadImage(assets::nomoon_png());
if (!img)
{
return;
}

constexpr float kGridCellSize = 20;
Path grid;
Expand Down Expand Up @@ -147,14 +143,17 @@ class MeshGM : public GM
{
ren->clipPath(PathBuilder::Circle(200, 200, 150));
}
ren->drawImageMesh(img.get(),
mesh.pts,
mesh.uvs,
mesh.indices,
vertexCount,
indexCount,
blendModes[i],
1.f - .1f * (i + 1));
if (img != nullptr)
{
ren->drawImageMesh(img.get(),
mesh.pts,
mesh.uvs,
mesh.indices,
vertexCount,
indexCount,
blendModes[i],
1.f - .1f * (i + 1));
}
ren->restore();
ren->translate(400, 0);
}
Expand Down

0 comments on commit acfc0e6

Please sign in to comment.