1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Typeface: Implement platform typefaces using Harfbuzz hb_font_t

This commit is contained in:
reuk 2024-02-26 16:42:32 +00:00
parent 080ac6e7e7
commit 0d2e34f34c
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
56 changed files with 8359 additions and 2985 deletions

View file

@ -430,8 +430,10 @@ struct AndroidDocument::Utils
std::unique_ptr<InputStream> createInputStream() const override
{
auto result = std::make_unique<AndroidContentUriInputStream> (uri);
return result->openedSuccessfully() ? std::move (result) : nullptr;
if (auto opened = AndroidContentUriInputStream::fromUri (uri))
return std::make_unique<AndroidContentUriInputStream> (std::move (*opened));
return {};
}
std::unique_ptr<OutputStream> createOutputStream() const override

View file

@ -584,14 +584,33 @@ struct AndroidStreamHelpers
};
//==============================================================================
struct AndroidContentUriInputStream final : public InputStream
class AndroidInputStreamWrapper final : public InputStream
{
explicit AndroidContentUriInputStream (const GlobalRef& uriIn)
: uri (uriIn),
stream (AndroidStreamHelpers::createStream (uri, AndroidStreamHelpers::StreamKind::input))
{}
public:
explicit AndroidInputStreamWrapper (jobject streamIn)
: stream (LocalRef<jobject> { streamIn })
{
}
~AndroidContentUriInputStream() override
AndroidInputStreamWrapper (AndroidInputStreamWrapper&& other) noexcept
: byteArray (std::exchange (other.byteArray, {})),
stream (std::exchange (other.stream, {})),
pos (std::exchange (other.pos, {})),
exhausted (std::exchange (other.exhausted, {}))
{
}
AndroidInputStreamWrapper (const AndroidInputStreamWrapper&) = delete;
AndroidInputStreamWrapper& operator= (AndroidInputStreamWrapper&& other) noexcept
{
std::swap (*this, other);
return *this;
}
AndroidInputStreamWrapper& operator= (const AndroidInputStreamWrapper&) = delete;
~AndroidInputStreamWrapper() override
{
getEnv()->CallVoidMethod (stream.get(), AndroidInputStream.close);
jniCheckHasExceptionOccurredAndClear();
@ -625,16 +644,9 @@ struct AndroidContentUriInputStream final : public InputStream
return result;
}
bool setPosition (int64 newPos) override
bool setPosition (int64) override
{
if (newPos == pos)
return true;
if (pos < newPos)
return skipImpl (newPos - pos);
AndroidContentUriInputStream (uri).swap (*this);
return skipImpl (newPos);
return false;
}
int64 getPosition() override
@ -642,8 +654,6 @@ struct AndroidContentUriInputStream final : public InputStream
return pos;
}
bool openedSuccessfully() const { return stream != nullptr; }
void skipNextBytes (int64 num) override
{
skipImpl (num);
@ -664,21 +674,107 @@ private:
return skipped == num;
}
auto tie() { return std::tie (uri, byteArray, stream, pos, exhausted); }
void swap (AndroidContentUriInputStream& other) noexcept
{
auto toSwap = other.tie();
tie().swap (toSwap);
}
GlobalRef uri;
CachedByteArray byteArray;
GlobalRef stream;
int64 pos = 0;
bool exhausted = false;
};
std::unique_ptr<InputStream> makeAndroidInputStreamWrapper (jobject stream);
std::unique_ptr<InputStream> makeAndroidInputStreamWrapper (jobject stream)
{
return std::make_unique<AndroidInputStreamWrapper> (stream);
}
//==============================================================================
struct AndroidContentUriInputStream final : public InputStream
{
AndroidContentUriInputStream (AndroidContentUriInputStream&& other) noexcept
: stream (std::move (other.stream)),
uri (std::exchange (other.uri, {}))
{
}
AndroidContentUriInputStream (const AndroidContentUriInputStream&) = delete;
AndroidContentUriInputStream& operator= (AndroidContentUriInputStream&& other) noexcept
{
std::swap (*this, other);
return *this;
}
AndroidContentUriInputStream& operator= (const AndroidContentUriInputStream&) = delete;
int64 getTotalLength() override
{
return stream.getTotalLength();
}
bool isExhausted() override
{
return stream.isExhausted();
}
int read (void* destBuffer, int maxBytesToRead) override
{
return stream.read (destBuffer, maxBytesToRead);
}
bool setPosition (int64 newPos) override
{
if (newPos == getPosition())
return true;
if (getPosition() < newPos)
return skipImpl (newPos - getPosition());
auto newStream = fromUri (uri);
if (! newStream.has_value())
return false;
*this = std::move (*newStream);
return skipImpl (newPos);
}
int64 getPosition() override
{
return stream.getPosition();
}
void skipNextBytes (int64 num) override
{
stream.skipNextBytes (num);
}
static std::optional<AndroidContentUriInputStream> fromUri (const GlobalRef& uriIn)
{
const auto nativeStream = AndroidStreamHelpers::createStream (uriIn, AndroidStreamHelpers::StreamKind::input);
if (nativeStream == nullptr)
return {};
return AndroidContentUriInputStream { AndroidInputStreamWrapper { nativeStream }, uriIn };
}
private:
AndroidContentUriInputStream (AndroidInputStreamWrapper streamIn, const GlobalRef& uriIn)
: stream (std::move (streamIn)),
uri (uriIn)
{
}
bool skipImpl (int64 num)
{
const auto oldPosition = getPosition();
skipNextBytes (num);
return getPosition() == oldPosition + num;
}
AndroidInputStreamWrapper stream;
GlobalRef uri;
};
//==============================================================================
class MediaScannerConnectionClient : public AndroidInterfaceImplementer
{