diff --git a/data/vs-standard.mse-style/text-mask.png b/data/vs-standard.mse-style/text-mask.png index 9fcf9d9c..8036d3b5 100644 Binary files a/data/vs-standard.mse-style/text-mask.png and b/data/vs-standard.mse-style/text-mask.png differ diff --git a/src/gfx/gfx.hpp b/src/gfx/gfx.hpp index 33be8e06..c85ded24 100644 --- a/src/gfx/gfx.hpp +++ b/src/gfx/gfx.hpp @@ -155,9 +155,11 @@ class ContourMask { ~ContourMask(); /// Load a contour mask - void load(const String& filename); + void load(const Image& image); /// Unload the mask void unload(); + /// Is a mask loaded? + inline bool ok() const { return width > 0 && height > 0; } /// Returns the start of a row, when the mask were stretched to size double rowLeft (double y, RealSize size) const; @@ -165,8 +167,8 @@ class ContourMask { double rowRight(double y, RealSize size) const; private: - UInt width, height; - UInt *lefts, *rights; + int width, height; + int *lefts, *rights; }; // ----------------------------------------------------------------------------- : Color utility functions diff --git a/src/gfx/mask_image.cpp b/src/gfx/mask_image.cpp index 23545701..618419cb 100644 --- a/src/gfx/mask_image.cpp +++ b/src/gfx/mask_image.cpp @@ -49,3 +49,53 @@ bool AlphaMask::isTransparent(int x, int y) const { } // ----------------------------------------------------------------------------- : ContourMask + +ContourMask::ContourMask() + : width(0), height(0), lefts(nullptr), rights(nullptr) +{} +ContourMask::~ContourMask() { + unload(); +} + +void ContourMask::load(const Image& image) { + unload(); + width = image.GetWidth(); + height = image.GetHeight(); + lefts = new int[height]; + rights = new int[height]; + // for each row: determine left and rightmost white pixel + Byte* data = image.GetData(); + for (int y = 0 ; y < height ; ++y) { + lefts[y] = width; rights[y] = width; + for (int x = 0 ; x < width ; ++x) { + int v = data[0] + data[1] + data[2]; + if (v > 50) { // white enough + rights[y] = x; + if (x < lefts[y]) lefts[y] = x; + } + data += 3; + } + } +} + +void ContourMask::unload() { + delete lefts; + delete rights; + lefts = rights = nullptr; + width = height = 0; +} + +double ContourMask::rowLeft (double y, RealSize size) const { + if (!ok() || y < 0 || y >= size.height) { + // no mask, or outside it + return 0; + } + return lefts[(int)(y * size.height / height)] * size.width / width; +} +double ContourMask::rowRight(double y, RealSize size) const { + if (!ok() || y < 0 || y >= size.height) { + // no mask, or outside it + return size.width; + } + return rights[(int)(y * size.height / height)] * size.width / width; +} diff --git a/src/render/text/viewer.cpp b/src/render/text/viewer.cpp index 86926cf9..88adb5c0 100644 --- a/src/render/text/viewer.cpp +++ b/src/render/text/viewer.cpp @@ -468,6 +468,11 @@ bool TextViewer::prepareLinesScale(RotatedDC& dc, const vector& chars, line.separator_after = false; // reset line_size line_size = RealSize(lineLeft(dc, style, line.top), 0); + while (line.top < style.height && line_size.width + 1 >= style.width - style.padding_right) { + // nothing fits on this line, move down one pixel + line.top += 1; + line_size = RealSize(lineLeft(dc, style, line.top), 0); + } line.positions.push_back(line_size.width); // start position } } @@ -487,17 +492,12 @@ bool TextViewer::prepareLinesScale(RotatedDC& dc, const vector& chars, } double TextViewer::lineLeft(RotatedDC& dc, const TextStyle& style, double y) { - return 0 + style.padding_left; -// return style.mask.rowLeft(y, dc.getInternalSize()) + style.padding_left; + return style.mask.rowLeft(y, dc.getInternalSize()) + style.padding_left; } double TextViewer::lineRight(RotatedDC& dc, const TextStyle& style, double y) { - return style.width - style.padding_right; -// return style.mask.rowRight(y, dc.getInternalSize()) - style.padding_right; + return style.mask.rowRight(y, dc.getInternalSize()) - style.padding_right; } -ContourMask::ContourMask() {} // MOVEME //@@ -ContourMask::~ContourMask() {} - void TextViewer::alignLines(RotatedDC& dc, const vector& chars, const TextStyle& style) { if (style.alignment == ALIGN_TOP_LEFT) return; // Find height of the text, don't count the last lines if they are empty diff --git a/src/render/value/text.cpp b/src/render/value/text.cpp index 14a26a61..52f1eb4b 100644 --- a/src/render/value/text.cpp +++ b/src/render/value/text.cpp @@ -8,10 +8,19 @@ #include #include +#include // ----------------------------------------------------------------------------- : TextValueViewer void TextValueViewer::draw(RotatedDC& dc) { + if (!style().mask_filename.empty() && !style().mask.ok()) { + // load contour mask + Image image; + InputStreamP image_file = viewer.stylesheet->openIn(style().mask_filename); + if (image.LoadFile(*image_file)) { + style().mask.load(image); + } + } drawFieldBorder(dc); v.prepare(dc, value().value(), style(), viewer.getContext()); v.draw(dc, style(), (DrawWhat)(