blob: f3dbe9dc9bea4d7fc7ded894adbec4a86eb34e45 [file]
/*
* Copyright 2022 Rive
*/
#ifndef _RIVE_FACTORY_HPP_
#define _RIVE_FACTORY_HPP_
#include "rive/renderer.hpp"
#include "rive/text_engine.hpp"
#include "rive/audio/audio_source.hpp"
#include "rive/refcnt.hpp"
#include "rive/span.hpp"
#include "rive/math/aabb.hpp"
#include <stdio.h>
#include <cstdint>
#include <vector>
namespace rive
{
class RawPath;
namespace ore
{
class Context;
}
namespace cmd
{
class DeferredCanvasHost;
}
class Factory
{
public:
Factory() {}
virtual ~Factory() {}
virtual rcp<RenderBuffer> makeRenderBuffer(
RenderBufferType,
RenderBufferFlags,
size_t sizeInBytes) = 0;
virtual rcp<ImageMeshInstances> makeImageMeshInstances(size_t count)
{
return make_rcp<ImageMeshInstances>(count);
}
virtual rcp<RenderShader> makeLinearGradient(
float sx,
float sy,
float ex,
float ey,
const ColorInt colors[], // [count]
const float stops[], // [count]
size_t count) = 0;
virtual rcp<RenderShader> makeRadialGradient(
float cx,
float cy,
float radius,
const ColorInt colors[], // [count]
const float stops[], // [count]
size_t count) = 0;
virtual rcp<RenderShader> makeAngularGradient(
const ColorInt colors[], // [count]
const float stops[], // [count]
size_t count)
{
// TODO: This is defaulted to make a linear gradient with a single stop
// (i.e. it's solid color) for platforms where angular gradients are not
// yet implemented, mostly to have it do *something*. This defaulting
// should get removed once there's an implementation everywhere (which
// may still be doing something like this if, as with the SVG renderer,
// this isn't possible to implement properly).
return makeLinearGradient(
0.0f,
0.0f,
1.0f,
0.0f,
colors,
stops,
std::min(size_t(1), count));
}
// Returns a full-formed RenderPath -- can be treated as immutable
// This call might swap out the arrays backing the points and verbs in the
// given RawPath, so the caller can expect it to be in an undefined state
// upon return.
virtual rcp<RenderPath> makeRenderPath(RawPath&, FillRule) = 0;
// Deprecated -- working to make RenderPath's immutable
virtual rcp<RenderPath> makeEmptyRenderPath() = 0;
virtual rcp<RenderPaint> makeRenderPaint() = 0;
virtual rcp<RenderImage> decodeImage(Span<const uint8_t>) = 0;
// GPU ore context, when this factory is backed by a RenderContext.
// Null for non-GPU factories. Kept last in the virtual section to avoid
// shifting existing vtable slots.
virtual ore::Context* ore() { return nullptr; }
// The GPU render context an import through this factory should give its
// scripts, as a Factory so this header stays free of gpu types. A render
// context answers with itself; a recording session answers with the one it
// records for, which on web is null until a render texture attaches, so
// callers that deferred an allocation ask again rather than caching the
// null they saw at import. Null means the importer cannot route GPU
// scripting.
virtual Factory* renderContext() { return nullptr; }
// Set when script canvas work must record rather than issue. Null means
// scripts draw straight to the driver.
virtual cmd::DeferredCanvasHost* deferredCanvasHost() { return nullptr; }
// A host that can hand out an offscreen frame to draw into, used by
// features that rasterize into a texture rather than to the screen (e.g.
// an artboard caching itself as a bitmap). A recording session doubles as
// one, which is the default.
//
// Kept separate from deferredCanvasHost() on purpose: that one answers
// "content is being recorded for a later replay", and the scripting layer
// keys canvas allocation and frame handling off it. A renderer that draws
// immediately can serve this hook, but must not answer that one.
virtual cmd::DeferredCanvasHost* canvasContentHost()
{
return deferredCanvasHost();
}
// Whether THIS device can apply a layer mask. Distinct from the hook of the
// same name on DeferredCanvasHost, which is the one a caller about to
// rasterize asks: that one is about the canvas being handed out, this one
// is about the device, and the two are different objects whenever a factory
// delegates its host elsewhere.
//
// It exists for exactly one caller. A recording session has to ask the
// context it will replay against, and all it holds is a Factory* -- which
// in a Canvas-2D build is not a render context at all, so it must dispatch
// rather than cast.
//
// No by default, matching the host hook and for the same reason: the
// default Renderer::applyLayerMask is itself a no-op, so a factory that has
// not answered is one whose renderer will drop the op -- and a yes here
// reaches a session, which reports support, which has the caller crop to
// the mask box on the way to dropping it. That is exactly the Canvas-2D
// case: its factory is not a render context and its renderer cannot apply
// the op. RenderContext and SerializingFactory opt in.
virtual bool supportsLayerMask() const { return false; }
rcp<Font> decodeFont(Span<const uint8_t>);
rcp<Font> decodeFont(std::vector<uint8_t>&&);
rcp<AudioSource> decodeAudio(Span<const uint8_t>);
// Non-virtual helpers
rcp<RenderPath> makeRenderPath(const AABB&);
};
} // namespace rive
#endif