diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
commit | cca66b9ec4e494c1d919bff0f71a820d8afab1fa (patch) | |
tree | 146f39ded1c938019e1ed42d30923c2ac9e86789 /src/libnrtype/Layout-TNG-Scanline-Maker.h | |
parent | Initial commit. (diff) | |
download | inkscape-upstream.tar.xz inkscape-upstream.zip |
Adding upstream version 1.2.2.upstream/1.2.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/libnrtype/Layout-TNG-Scanline-Maker.h | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/libnrtype/Layout-TNG-Scanline-Maker.h b/src/libnrtype/Layout-TNG-Scanline-Maker.h new file mode 100644 index 0000000..c8c8232 --- /dev/null +++ b/src/libnrtype/Layout-TNG-Scanline-Maker.h @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Text::Layout::ScanlineMaker - text layout engine shape measurers + * + * Authors: + * Richard Hughes <cyreve@users.sf.net> + * + * Copyright (C) 2005 Richard Hughes + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ +#ifndef __LAYOUT_TNG_SCANLINE_MAKER_H__ +#define __LAYOUT_TNG_SCANLINE_MAKER_H__ + +#include <vector> +#include <cmath> +#include "libnrtype/Layout-TNG.h" + +class Shape; + +namespace Inkscape { +namespace Text { + +/** \brief private to Layout. Generates lists of chunks within a shape. + +This is the abstract base class for taking a given shape and scanning through +it line-by-line to get the horizontal extents of each chunk for a line of a +given height. There are two specialisations: One for real shapes and one that +turns off wrapping by simulating an infinite shape. In due course there will +be a further specialisation to optimise for the common case where the shape +is a rectangle. +*/ +class Layout::ScanlineMaker +{ +public: + virtual ~ScanlineMaker() = default; + + struct ScanRun { + double y; /// that's the top of the scan run, not the baseline + double x_start; // these are not flipped according to the text direction + double x_end; + inline double width() const {return std::abs(x_start - x_end);} + }; + + /** Returns a list of chunks on the current line which can fit text with + the given properties. It is up to the caller to discard any chunks which + are too narrow for its needs. This function may change the y coordinate + between calls if the new height too big to fit in the space remaining in + this shape. Returns an empty vector if there is no space left in the + current shape. */ + virtual std::vector<ScanRun> makeScanline(Layout::FontMetrics const &line_height) =0; + + /** Indicates that the caller has successfully filled the current line + and hence that the next call to makeScanline() should return lines on + the next lower line. There is no error return, the next call to + makeScanline() will give an error if there is no more space. */ + virtual void completeLine() =0; + + /** Returns the y coordinate of the top of the scanline that will be + returned by the next call to makeScanline(). */ + virtual double yCoordinate() = 0; + + /** Forces an arbitrary change in the stored y coordinate of the object. + The next call to makeScanline() will return runs whose top is at + the new coordinate. */ + virtual void setNewYCoordinate(double new_y) =0; + + /** Tests whether the caller can fit a new line with the given metrics + into exactly the space returned by the previous call to makeScanline(). + This saves the caller from having to discard its wrapping solution and + starting at the beginning of the line again when a larger font is seen. + The metrics given here are considered to be the ones that are being + used now, and hence is the line advance height used by completeLine(). + */ + virtual bool canExtendCurrentScanline(Layout::FontMetrics const &line_height) =0; + + /** Sets current line block height. Call before completeLine() to correct for + actually used line height (in case some chunks with larger font-size rolled back). + */ + virtual void setLineHeight(Layout::FontMetrics const &line_height) =0; +}; + +/** \brief private to Layout. Generates infinite scanlines for when you don't want wrapping + +This is a 'fake' scanline maker which will always return infinite results, +effectively turning off wrapping. It's a very simple implementation. + +It does have the curious property, however, that the input coordinates are +'real' x and y, but the outputs are rotated according to the +\a block_progression. +*/ +class Layout::InfiniteScanlineMaker : public Layout::ScanlineMaker +{ +public: + InfiniteScanlineMaker(double initial_x, double initial_y, Layout::Direction block_progression); + ~InfiniteScanlineMaker() override; + + /** Returns a single infinite run at the current location */ + std::vector<ScanRun> makeScanline(Layout::FontMetrics const &line_height) override; + + /** Increments the current y by the current line height */ + void completeLine() override; + + double yCoordinate() override + {return _y;} + + /** Just changes y */ + void setNewYCoordinate(double new_y) override; + + /** Always true, but has to save the new height */ + bool canExtendCurrentScanline(Layout::FontMetrics const &line_height) override; + + /** Sets current line block height. Call before completeLine() to correct for + actually used line height (in case some chunks with larger font-size rolled back). + */ + void setLineHeight(Layout::FontMetrics const &line_height) override; + +private: + double _x, _y; + Layout::FontMetrics _current_line_height; + bool _negative_block_progression; /// if true, indicates that completeLine() should decrement rather than increment, ie block-progression is either rl or bt +}; + +/** \brief private to Layout. Generates scanlines inside an arbitrary shape + +This is the 'perfect', and hence slowest, implementation of a +Layout::ScanlineMaker, which will return exact bounds for any given +input shape. +*/ +class Layout::ShapeScanlineMaker : public Layout::ScanlineMaker +{ +public: + ShapeScanlineMaker(Shape const *shape, Layout::Direction block_progression); + ~ShapeScanlineMaker() override; + + std::vector<ScanRun> makeScanline(Layout::FontMetrics const &line_height) override; + + void completeLine() override; + + double yCoordinate() override; + + void setNewYCoordinate(double new_y) override; + + /** never true */ + bool canExtendCurrentScanline(Layout::FontMetrics const &line_height) override; + + /** Sets current line block height. Call before completeLine() to correct for + actually used line height (in case some chunks with larger font-size rolled back). + */ + void setLineHeight(Layout::FontMetrics const &line_height) override; + +private: + /** To generate scanlines for top-to-bottom text it is easiest if we + simply rotate the given shape by a multiple of 90 degrees. This stores + that. If no rotation was needed we can simply store the pointer we were + given and set shape_needs_freeing appropriately. */ + Shape *_rotated_shape; + + /// see #rotated_shape; + bool _shape_needs_freeing; + + // Shape::BeginRaster() needs floats rather than doubles + float _bounding_box_top, _bounding_box_bottom; + float _y; + float _rasterizer_y; + int _current_rasterization_point; + float _current_line_height; + + bool _negative_block_progression; /// if true, indicates that completeLine() should decrement rather than increment, ie block-progression is either rl or bt +}; + +}//namespace Text +}//namespace Inkscape + +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |