blob: 19710c464cf1b7ba82eb4427efa49dc54a807235 [file] [log] [blame]
/*
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIB_TXT_SRC_PARAGRAPH_H_
#define LIB_TXT_SRC_PARAGRAPH_H_
#include "line_metrics.h"
#include "paragraph_style.h"
class SkCanvas;
namespace txt {
// Interface for text layout engines. The original implementation was based on
// the Minikin text layout library used by Android. Another implementation is
// available based on Skia's SkShaper/SkParagraph text layout module.
class Paragraph {
public:
enum Affinity { UPSTREAM, DOWNSTREAM };
// Options for various types of bounding boxes provided by
// GetRectsForRange(...).
enum class RectHeightStyle {
// Provide tight bounding boxes that fit heights per run.
kTight,
// The height of the boxes will be the maximum height of all runs in the
// line. All rects in the same line will be the same height.
kMax,
// Extends the top and/or bottom edge of the bounds to fully cover any line
// spacing. The top edge of each line should be the same as the bottom edge
// of the line above. There should be no gaps in vertical coverage given any
// ParagraphStyle line_height.
//
// The top and bottom of each rect will cover half of the
// space above and half of the space below the line.
kIncludeLineSpacingMiddle,
// The line spacing will be added to the top of the rect.
kIncludeLineSpacingTop,
// The line spacing will be added to the bottom of the rect.
kIncludeLineSpacingBottom,
// Calculate boxes based on the strut's metrics.
kStrut
};
enum class RectWidthStyle {
// Provide tight bounding boxes that fit widths to the runs of each line
// independently.
kTight,
// Extends the width of the last rect of each line to match the position of
// the widest rect over all the lines.
kMax
};
struct PositionWithAffinity {
const size_t position;
const Affinity affinity;
PositionWithAffinity(size_t p, Affinity a) : position(p), affinity(a) {}
};
struct TextBox {
SkRect rect;
TextDirection direction;
TextBox(SkRect r, TextDirection d) : rect(r), direction(d) {}
};
template <typename T>
struct Range {
Range() : start(), end() {}
Range(T s, T e) : start(s), end(e) {}
T start, end;
bool operator==(const Range<T>& other) const {
return start == other.start && end == other.end;
}
T width() const { return end - start; }
void Shift(T delta) {
start += delta;
end += delta;
}
};
virtual ~Paragraph() = default;
// Returns the width provided in the Layout() method. This is the maximum
// width any line in the laid out paragraph can occupy. We expect that
// GetMaxWidth() >= GetLayoutWidth().
virtual double GetMaxWidth() = 0;
// Returns the height of the laid out paragraph. NOTE this is not a tight
// bounding height of the glyphs, as some glyphs do not reach as low as they
// can.
virtual double GetHeight() = 0;
// Returns the width of the longest line as found in Layout(), which is
// defined as the horizontal distance from the left edge of the leftmost glyph
// to the right edge of the rightmost glyph. We expect that
// GetLongestLine() <= GetMaxWidth().
virtual double GetLongestLine() = 0;
// Returns the actual max width of the longest line after Layout().
virtual double GetMinIntrinsicWidth() = 0;
// Returns the total width covered by the paragraph without linebreaking.
virtual double GetMaxIntrinsicWidth() = 0;
// Distance from top of paragraph to the Alphabetic baseline of the first
// line. Used for alphabetic fonts (A-Z, a-z, greek, etc.)
virtual double GetAlphabeticBaseline() = 0;
// Distance from top of paragraph to the Ideographic baseline of the first
// line. Used for ideographic fonts (Chinese, Japanese, Korean, etc.)
virtual double GetIdeographicBaseline() = 0;
// Checks if the layout extends past the maximum lines and had to be
// truncated.
virtual bool DidExceedMaxLines() = 0;
// Layout calculates the positioning of all the glyphs. Must call this method
// before Painting and getting any statistics from this class.
virtual void Layout(double width) = 0;
// Paints the laid out text onto the supplied SkCanvas at (x, y) offset from
// the origin. Only valid after Layout() is called.
virtual void Paint(SkCanvas* canvas, double x, double y) = 0;
// Returns a vector of bounding boxes that enclose all text between start and
// end glyph indexes, including start and excluding end.
virtual std::vector<TextBox> GetRectsForRange(
size_t start,
size_t end,
RectHeightStyle rect_height_style,
RectWidthStyle rect_width_style) = 0;
// Returns a vector of bounding boxes that bound all inline placeholders in
// the paragraph.
//
// There will be one box for each inline placeholder. The boxes will be in the
// same order as they were added to the paragraph. The bounds will always be
// tight and should fully enclose the area where the placeholder should be.
//
// More granular boxes may be obtained through GetRectsForRange, which will
// return bounds on both text as well as inline placeholders.
virtual std::vector<TextBox> GetRectsForPlaceholders() = 0;
// Returns the index of the glyph that corresponds to the provided coordinate,
// with the top left corner as the origin, and +y direction as down.
virtual PositionWithAffinity GetGlyphPositionAtCoordinate(double dx,
double dy) = 0;
// Finds the first and last glyphs that define a word containing the glyph at
// index offset.
virtual Range<size_t> GetWordBoundary(size_t offset) = 0;
virtual std::vector<LineMetrics>& GetLineMetrics() = 0;
};
} // namespace txt
#endif // LIB_TXT_SRC_PARAGRAPH_H_