1cb93a386Sopenharmony_ci// Copyright 2019 Google LLC. 2cb93a386Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. 3cb93a386Sopenharmony_ci#ifndef editor_DEFINED 4cb93a386Sopenharmony_ci#define editor_DEFINED 5cb93a386Sopenharmony_ci 6cb93a386Sopenharmony_ci#include "modules/skplaintexteditor/include/stringslice.h" 7cb93a386Sopenharmony_ci#include "modules/skplaintexteditor/include/stringview.h" 8cb93a386Sopenharmony_ci 9cb93a386Sopenharmony_ci#include "include/core/SkColor.h" 10cb93a386Sopenharmony_ci#include "include/core/SkFont.h" 11cb93a386Sopenharmony_ci#include "include/core/SkString.h" 12cb93a386Sopenharmony_ci#include "include/core/SkTextBlob.h" 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_ci#include <climits> 15cb93a386Sopenharmony_ci#include <cstdint> 16cb93a386Sopenharmony_ci#include <utility> 17cb93a386Sopenharmony_ci#include <vector> 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ciclass SkCanvas; 20cb93a386Sopenharmony_ciclass SkShaper; 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_cinamespace SkPlainTextEditor { 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ciclass Editor { 25cb93a386Sopenharmony_ci struct TextLine; 26cb93a386Sopenharmony_cipublic: 27cb93a386Sopenharmony_ci // total height in canvas display units. 28cb93a386Sopenharmony_ci int getHeight() const { return fHeight; } 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci // set display width in canvas display units 31cb93a386Sopenharmony_ci void setWidth(int w); // may force re-shape 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci // get/set current font (used for shaping and displaying text) 34cb93a386Sopenharmony_ci const SkFont& font() const { return fFont; } 35cb93a386Sopenharmony_ci void setFont(SkFont font); 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ci struct Text { 38cb93a386Sopenharmony_ci const std::vector<TextLine>& fLines; 39cb93a386Sopenharmony_ci struct Iterator { 40cb93a386Sopenharmony_ci std::vector<TextLine>::const_iterator fPtr; 41cb93a386Sopenharmony_ci StringView operator*() { return fPtr->fText.view(); } 42cb93a386Sopenharmony_ci void operator++() { ++fPtr; } 43cb93a386Sopenharmony_ci bool operator!=(const Iterator& other) const { return fPtr != other.fPtr; } 44cb93a386Sopenharmony_ci }; 45cb93a386Sopenharmony_ci Iterator begin() const { return Iterator{fLines.begin()}; } 46cb93a386Sopenharmony_ci Iterator end() const { return Iterator{fLines.end()}; } 47cb93a386Sopenharmony_ci }; 48cb93a386Sopenharmony_ci // Loop over all the lines of text. The lines are not '\0'- or '\n'-terminated. 49cb93a386Sopenharmony_ci // For example, to dump the entire file to standard output: 50cb93a386Sopenharmony_ci // for (SkPlainTextEditor::StringView str : editor.text()) { 51cb93a386Sopenharmony_ci // std::cout.write(str.data, str.size) << '\n'; 52cb93a386Sopenharmony_ci // } 53cb93a386Sopenharmony_ci Text text() const { return Text{fLines}; } 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci // get size of line in canvas display units. 56cb93a386Sopenharmony_ci int lineHeight(size_t index) const { return fLines[index].fHeight; } 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci struct TextPosition { 59cb93a386Sopenharmony_ci size_t fTextByteIndex = SIZE_MAX; // index into UTF-8 representation of line. 60cb93a386Sopenharmony_ci size_t fParagraphIndex = SIZE_MAX; // logical line, based on hard newline characters. 61cb93a386Sopenharmony_ci }; 62cb93a386Sopenharmony_ci enum class Movement { 63cb93a386Sopenharmony_ci kNowhere, 64cb93a386Sopenharmony_ci kLeft, 65cb93a386Sopenharmony_ci kUp, 66cb93a386Sopenharmony_ci kRight, 67cb93a386Sopenharmony_ci kDown, 68cb93a386Sopenharmony_ci kHome, 69cb93a386Sopenharmony_ci kEnd, 70cb93a386Sopenharmony_ci kWordLeft, 71cb93a386Sopenharmony_ci kWordRight, 72cb93a386Sopenharmony_ci }; 73cb93a386Sopenharmony_ci TextPosition move(Editor::Movement move, Editor::TextPosition pos) const; 74cb93a386Sopenharmony_ci TextPosition getPosition(SkIPoint); 75cb93a386Sopenharmony_ci SkRect getLocation(TextPosition); 76cb93a386Sopenharmony_ci // insert into current text. 77cb93a386Sopenharmony_ci TextPosition insert(TextPosition, const char* utf8Text, size_t byteLen); 78cb93a386Sopenharmony_ci // remove text between two positions 79cb93a386Sopenharmony_ci TextPosition remove(TextPosition, TextPosition); 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci // If dst is nullptr, returns size of given selection. 82cb93a386Sopenharmony_ci // Otherwise, fill dst with a copy of the selection, and return the amount copied. 83cb93a386Sopenharmony_ci size_t copy(TextPosition pos1, TextPosition pos2, char* dst = nullptr) const; 84cb93a386Sopenharmony_ci size_t lineCount() const { return fLines.size(); } 85cb93a386Sopenharmony_ci StringView line(size_t i) const { 86cb93a386Sopenharmony_ci return i < fLines.size() ? fLines[i].fText.view() : StringView{nullptr, 0}; 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci struct PaintOpts { 90cb93a386Sopenharmony_ci SkColor4f fBackgroundColor = {1, 1, 1, 1}; 91cb93a386Sopenharmony_ci SkColor4f fForegroundColor = {0, 0, 0, 1}; 92cb93a386Sopenharmony_ci // TODO: maybe have multiple selections and cursors, each with separate colors. 93cb93a386Sopenharmony_ci SkColor4f fSelectionColor = {0.729f, 0.827f, 0.988f, 1}; 94cb93a386Sopenharmony_ci SkColor4f fCursorColor = {1, 0, 0, 1}; 95cb93a386Sopenharmony_ci TextPosition fSelectionBegin; 96cb93a386Sopenharmony_ci TextPosition fSelectionEnd; 97cb93a386Sopenharmony_ci TextPosition fCursor; 98cb93a386Sopenharmony_ci }; 99cb93a386Sopenharmony_ci void paint(SkCanvas* canvas, PaintOpts); 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ciprivate: 102cb93a386Sopenharmony_ci // TODO: rename this to TextParagraph. fLines to fParas. 103cb93a386Sopenharmony_ci struct TextLine { 104cb93a386Sopenharmony_ci StringSlice fText; 105cb93a386Sopenharmony_ci sk_sp<const SkTextBlob> fBlob; 106cb93a386Sopenharmony_ci std::vector<SkRect> fCursorPos; 107cb93a386Sopenharmony_ci std::vector<size_t> fLineEndOffsets; 108cb93a386Sopenharmony_ci std::vector<bool> fWordBoundaries; 109cb93a386Sopenharmony_ci SkIPoint fOrigin = {0, 0}; 110cb93a386Sopenharmony_ci int fHeight = 0; 111cb93a386Sopenharmony_ci bool fShaped = false; 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci TextLine(StringSlice t) : fText(std::move(t)) {} 114cb93a386Sopenharmony_ci TextLine() {} 115cb93a386Sopenharmony_ci }; 116cb93a386Sopenharmony_ci std::vector<TextLine> fLines; 117cb93a386Sopenharmony_ci int fWidth = 0; 118cb93a386Sopenharmony_ci int fHeight = 0; 119cb93a386Sopenharmony_ci SkFont fFont; 120cb93a386Sopenharmony_ci bool fNeedsReshape = false; 121cb93a386Sopenharmony_ci const char* fLocale = "en"; // TODO: make this setable 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_ci void markDirty(TextLine*); 124cb93a386Sopenharmony_ci void reshapeAll(); 125cb93a386Sopenharmony_ci}; 126cb93a386Sopenharmony_ci} // namespace SkPlainTextEditor 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_cistatic inline bool operator==(const SkPlainTextEditor::Editor::TextPosition& u, 129cb93a386Sopenharmony_ci const SkPlainTextEditor::Editor::TextPosition& v) { 130cb93a386Sopenharmony_ci return u.fParagraphIndex == v.fParagraphIndex && u.fTextByteIndex == v.fTextByteIndex; 131cb93a386Sopenharmony_ci} 132cb93a386Sopenharmony_cistatic inline bool operator!=(const SkPlainTextEditor::Editor::TextPosition& u, 133cb93a386Sopenharmony_ci const SkPlainTextEditor::Editor::TextPosition& v) { return !(u == v); } 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_cistatic inline bool operator<(const SkPlainTextEditor::Editor::TextPosition& u, 136cb93a386Sopenharmony_ci const SkPlainTextEditor::Editor::TextPosition& v) { 137cb93a386Sopenharmony_ci return u.fParagraphIndex < v.fParagraphIndex || 138cb93a386Sopenharmony_ci (u.fParagraphIndex == v.fParagraphIndex && u.fTextByteIndex < v.fTextByteIndex); 139cb93a386Sopenharmony_ci} 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci#endif // editor_DEFINED 143