blob: 3bbbb45db5f11a2841f039a221bf73a0ffc77e4a [file] [log] [blame]
// Copyright 2019 Google LLC.
#ifndef TextLine_DEFINED
#define TextLine_DEFINED
#include "include/core/SkCanvas.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTHash.h"
#include "modules/skparagraph/include/DartTypes.h"
#include "modules/skparagraph/include/TextStyle.h"
#include "modules/skparagraph/src/Run.h"
#include "src/core/SkSpan.h"
namespace skia {
namespace textlayout {
class TextLine {
public:
TextLine() = default;
~TextLine() = default;
TextLine(ParagraphImpl* master,
SkVector offset,
SkVector advance,
BlockRange blocks,
TextRange text,
TextRange textWithSpaces,
ClusterRange clusters,
ClusterRange clustersWithGhosts,
SkScalar widthWithSpaces,
LineMetrics sizes);
inline void setMaster(ParagraphImpl* master) { fMaster = master; }
inline TextRange trimmedText() const { return fTextRange; }
inline TextRange textWithSpaces() const { return fTextWithWhitespacesRange; }
inline Run* ellipsis() const { return fEllipsis.get(); }
inline LineMetrics sizes() const { return fSizes; }
inline bool empty() const { return fTextRange.empty(); }
inline SkScalar height() const { return fAdvance.fY; }
SkScalar width() const {
return fAdvance.fX + (fEllipsis != nullptr ? fEllipsis->fAdvance.fX : 0);
}
inline SkScalar shift() const { return fShift; }
SkScalar widthWithSpaces() const { return fWidthWithSpaces; }
SkVector offset() const;
inline SkScalar alphabeticBaseline() const { return fSizes.alphabeticBaseline(); }
inline SkScalar ideographicBaseline() const { return fSizes.ideographicBaseline(); }
inline SkScalar baseline() const { return fSizes.baseline(); }
inline SkScalar roundingDelta() const { return fSizes.delta(); }
using StyleVisitor = std::function<SkScalar(TextRange textRange, const TextStyle& style,
SkScalar offsetX)>;
void iterateThroughStylesInTextOrder(StyleType styleType, const StyleVisitor& visitor) const;
using RunVisitor = std::function<bool(Run* run, size_t pos, size_t size, SkRect clip,
SkScalar shift, bool clippingNeeded)>;
SkScalar iterateThroughRuns(TextRange textRange,
SkScalar offsetX,
bool includeGhostWhitespaces,
const RunVisitor& visitor) const;
using ClustersVisitor = std::function<bool(const Cluster* cluster, ClusterIndex index)>;
void iterateThroughClustersInGlyphsOrder(bool reverse, const ClustersVisitor& visitor) const;
void format(TextAlign effectiveAlign, SkScalar maxWidth);
void paint(SkCanvas* canvas);
void createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool ltr);
// For testing internal structures
void scanStyles(StyleType style, const StyleVisitor& visitor);
void scanRuns(const RunVisitor& visitor);
TextAlign assumedTextAlign() const;
private:
Run* shapeEllipsis(const SkString& ellipsis, Run* run);
void justify(SkScalar maxWidth);
SkRect measureTextInsideOneRun(TextRange textRange,
Run* run,
size_t& pos,
size_t& size,
bool includeGhostSpaces,
bool& clippingNeeded) const;
SkScalar paintText(SkCanvas* canvas, TextRange textRange, const TextStyle& style, SkScalar offsetX) const;
SkScalar paintBackground(SkCanvas* canvas, TextRange textRange, const TextStyle& style,
SkScalar offsetX) const;
SkScalar paintShadow(SkCanvas* canvas, TextRange textRange, const TextStyle& style,
SkScalar offsetX) const;
SkScalar paintDecorations(SkCanvas* canvas, TextRange textRange, const TextStyle& style,
SkScalar offsetX) const;
void computeDecorationPaint(SkPaint& paint, SkRect clip, const TextStyle& style,
SkPath& path) const;
bool contains(const Cluster* cluster) const {
return fTextRange.contains(cluster->textRange());
}
ParagraphImpl* fMaster;
BlockRange fBlockRange;
TextRange fTextRange;
TextRange fTextWithWhitespacesRange;
ClusterRange fClusterRange;
ClusterRange fGhostClusterRange;
SkTArray<size_t, true> fLogical;
SkVector fAdvance; // Text size
SkVector fOffset; // Text position
SkScalar fShift; // Left right
SkScalar fWidthWithSpaces;
std::shared_ptr<Run> fEllipsis; // In case the line ends with the ellipsis
LineMetrics fSizes; // Line metrics as a max of all run metrics
bool fHasBackground;
bool fHasShadows;
bool fHasDecorations;
// TODO: use for ellipsis the common cache
static SkTHashMap<SkFont, Run> fEllipsisCache; // All found so far shapes of ellipsis
};
} // namespace textlayout
} // namespace skia
#endif // TextLine_DEFINED