Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ The release run heads these entries with the version and opens a fresh

## Unreleased

- A StarView metafile draws its gradients, hatches and transparent shapes:
`GRADIENT`, `GRADIENTEX`, `HATCH` and `TRANSPARENT`.

- A spreadsheet decodes in less memory: 626 MB peak instead of 914 MB on a
297 MB `content.xml`. Rendered output is unchanged.

Expand Down
5 changes: 3 additions & 2 deletions src/odr/internal/svm/PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ Each stage is one pull request, stacked on the one before it.
which stencils one colour through a bitmap, and `ZCOMPRESS`, which needs
inflating first, are still open. See the shortcut below.
6. **Primitives** - done.
7. **Fills and transparency.** `GRADIENT`, `GRADIENTEX`, `HATCH`,
`WALLPAPER`, `TRANSPARENT`, `FLOATTRANSPARENT`.
7. **Fills and transparency** - `GRADIENT`, `GRADIENTEX`, `HATCH` and
`TRANSPARENT` are done. `WALLPAPER` and `FLOATTRANSPARENT` are not: the
first has a format of its own, the second nests a whole metafile.
8. **The map mode's unit** (#772 defect 6), see below.
9. **Stretch.** BΓ©zier flags (#772 defect 4), the `EPS` substitute metafile,
and version-1 (pre-`VCLMTF`) files via `SvmConverter.cxx`.
Expand Down
60 changes: 60 additions & 0 deletions src/odr/internal/svm/svm_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,66 @@ svm::BitmapAction svm::read_bitmap_action(std::istream &in,
return result;
}

std::uint32_t svm::read_object_color(std::istream &in) {
// `COL_NAME_USER`: the id that means three channels follow
constexpr std::uint16_t color_name_user = 0x8000;
// the palette `GenericTypeSerializer::readColor` indexes, its system colours
// resolved as it resolves them
static constexpr std::array<std::uint32_t, 31> palette = {
0x000000, 0x000080, 0x008000, 0x008080, 0x800000, 0x800080, 0x808000,
0x808080, 0xc0c0c0, 0x0000ff, 0x00ff00, 0x00ffff, 0xff0000, 0xff00ff,
0xffff00, 0xffffff, 0xffffff, 0x000000, 0xffffff, 0x000000, 0x000000,
0xffffff, 0x000000, 0xffffff, 0x000000, 0xc0c0c0, 0xffffff, 0x808080,
0xc0c0c0, 0xffffff, 0x000000};

std::uint16_t name{};
read_primitive(in, name);

if ((name & color_name_user) == 0) {
return name < palette.size() ? palette[name] : 0;
}

std::uint16_t red{};
std::uint16_t green{};
std::uint16_t blue{};
read_primitive(in, red);
read_primitive(in, green);
read_primitive(in, blue);
return static_cast<std::uint32_t>(red >> 8) << 16 |
static_cast<std::uint32_t>(green >> 8) << 8 |
static_cast<std::uint32_t>(blue >> 8);
}

svm::Gradient svm::read_gradient(std::istream &in) {
Gradient result;

read_version_length(in);
read_primitive(in, result.style);
result.start_color = read_object_color(in);
result.end_color = read_object_color(in);
read_primitive(in, result.angle);
read_primitive(in, result.border);
read_primitive(in, result.offset_x);
read_primitive(in, result.offset_y);
read_primitive(in, result.start_intensity);
read_primitive(in, result.end_intensity);
read_primitive(in, result.step_count);

return result;
}

svm::Hatch svm::read_hatch(std::istream &in) {
Hatch result;

read_version_length(in);
read_primitive(in, result.style);
result.color = read_object_color(in);
read_primitive(in, result.distance);
read_primitive(in, result.angle);

return result;
}

std::optional<svm::Region> svm::read_region(std::istream &in) {
const VersionLength vl = read_version_length(in);
std::uint16_t content_version{};
Expand Down
50 changes: 50 additions & 0 deletions src/odr/internal/svm/svm_format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,23 @@ enum MetaFontStrikeout {
STRIKEOUT_NONE = 0,
};

/// `awt::GradientStyle`.
enum MetaGradientStyle {
GRADIENT_LINEAR = 0,
GRADIENT_AXIAL = 1,
GRADIENT_RADIAL = 2,
GRADIENT_ELLIPTICAL = 3,
GRADIENT_SQUARE = 4,
GRADIENT_RECT = 5,
};

/// `HatchStyle`: one set of lines, two crossing, or three.
enum MetaHatchStyle {
HATCH_SINGLE = 0,
HATCH_DOUBLE = 1,
HATCH_TRIPLE = 2,
};

/// `LineStyle`, what a `LineInfo` draws with.
enum MetaLineStyle {
LINE_NONE = 0,
Expand Down Expand Up @@ -294,6 +311,33 @@ struct TextRectangleAction final {
std::uint16_t style{};
};

/// `Gradient`: the two colours, which way the ramp runs, and where it sits.
struct Gradient final {
std::uint16_t style{};
std::uint32_t start_color{};
std::uint32_t end_color{};
/// Tenths of a degree, counter-clockwise.
std::uint16_t angle{};
/// Percent of the ramp the start colour holds before it ramps.
std::uint16_t border{};
/// Percent of the bounds, where a complex gradient's centre sits.
std::uint16_t offset_x{};
std::uint16_t offset_y{};
/// Percent, what the colours are scaled by.
std::uint16_t start_intensity{100};
std::uint16_t end_intensity{100};
std::uint16_t step_count{};
};

/// `Hatch`: the lines drawn across a shape.
struct Hatch final {
std::uint16_t style{};
std::uint32_t color{};
std::int32_t distance{};
/// Tenths of a degree, counter-clockwise.
std::uint16_t angle{};
};

/// A clip region: bands covering it as a union of rectangles, and from
/// version 2 the poly-polygon those were rasterised from. An *empty* region
/// covers nothing and so clips everything away; `REGION_NULL`, which does not
Expand Down Expand Up @@ -394,6 +438,12 @@ TextLineAction read_text_line_action(std::istream &in, const VersionLength &vl);
std::uint16_t read_push_action(std::istream &in, const VersionLength &vl);
/// The `TextAlign` of a `TEXTALIGN`.
std::uint16_t read_text_align_action(std::istream &in);
/// A colour *inside* an object, which is not the plain `uint32` an action's
/// own colour is: `GenericTypeSerializer::readColor` reads a name id, and only
/// the user one carries three 16-bit channels behind it.
std::uint32_t read_object_color(std::istream &in);
Gradient read_gradient(std::istream &in);
Hatch read_hatch(std::istream &in);
/// A region, as `ReadRegion` reads one: a band list, and from version 2 the
/// poly-polygon it came from. `std::nullopt` where it does not clip at all.
std::optional<Region> read_region(std::istream &in);
Expand Down
Loading
Loading