1 /* 2 For general Scribus (>=1.3.2) copyright and licensing information please refer 3 to the COPYING file provided with the program. Following this notice may exist 4 a copyright and/or license notice that predates the release of Scribus 1.3.2 5 for which a new license (GPL+exception) is in place. 6 */ 7 8 #ifndef BOXES_H 9 #define BOXES_H 10 11 #include "glyphcluster.h" 12 #include "sctextstruct.h" 13 #include "itextcontext.h" 14 15 class StoryText; 16 class TextLayoutPainter; 17 class ScreenPainter; 18 19 /** 20 Class Box has a similar role as TeX's boxes. 21 Scribus packs glyph runs into GlyphBoxes, GlyphBoxes and ObjectBoxes into LineBoxes 22 and LineBoxes into GroupBox(T_Block). 23 (and in the future: math atoms, tables & table cells, ...) 24 */ 25 class Box 26 { 27 public: 28 enum BoxType 29 { 30 T_Invalid, 31 T_Block, 32 T_Line, 33 T_PathLine, 34 T_Glyph, 35 T_Object 36 }; 37 38 enum BoxDirection 39 { 40 D_Horizontal, 41 D_Vertical 42 }; 43 Box()44 Box() 45 { 46 m_type = T_Invalid; 47 m_direction = D_Horizontal; 48 m_x = m_y = m_width = m_ascent = m_descent = 0; 49 m_firstChar = 0; 50 m_lastChar = 0; 51 m_naturalAscent = 0; 52 m_naturalDescent = 0; 53 } 54 ~Box()55 virtual ~Box() 56 { 57 while (!m_boxes.isEmpty()) 58 delete m_boxes.takeFirst(); 59 } 60 61 /// The x position of the box relative to its parent. x()62 double x() const { return m_x; } 63 /// The y position of the box relative to its parent. y()64 double y() const { return m_y; } 65 /// Sets x and y positions of the box. moveTo(double x,double y)66 void moveTo (double x, double y) { m_x = x, m_y = y; } 67 /// Increments x and y positions of the box. moveBy(double x,double y)68 void moveBy (double x, double y) { m_x += x, m_y += y; } 69 70 /// The box width, can be different from its natural width. width()71 double width() const { return m_width; } 72 /// Set the box width. setWidth(double w)73 void setWidth(double w) { m_width = w; } 74 75 /// The box ascender above baseline. ascent()76 double ascent() const { return m_ascent; } 77 /// The box descender below baseline. descent()78 double descent() const { return m_descent; } 79 /// The box height, can be different from its natural height. height()80 double height() const { return m_ascent - m_descent; } 81 /// Set the box ascender. setAscent(double a)82 void setAscent(double a) { m_ascent = a; } 83 /// Set the box descender. setDescent(double d)84 void setDescent(double d) { m_descent = d; } 85 86 /// The actual width of the box contents, can be different from the requested width. naturalWidth()87 virtual double naturalWidth() const { return width(); } 88 /// The actual height of the box contents, can be different from the requested height. naturalHeight()89 virtual double naturalHeight() const { return height(); } 90 91 /// The bounding box and position of the box relative to its parent. bbox()92 QRectF bbox() const { return QRectF(m_x, m_y, m_width, height()); } 93 94 /// Whether the coordinate is inside the box or not. containsPoint(QPointF coord)95 virtual bool containsPoint(QPointF coord) const { return bbox().contains(coord); } 96 /// Whether the character at index pos is inside the box or not. containsPos(int pos)97 bool containsPos(int pos) const { return firstChar() <= pos && pos <= lastChar(); } 98 99 /// Returns the character index at coorddinate. 100 virtual int pointToPosition(QPointF coord, const StoryText &story) const = 0; 101 /// Returns the position of cursor before the character at index pos. positionToPoint(int,const StoryText &)102 virtual QLineF positionToPoint(int, const StoryText&) const { return QLineF(); } 103 104 /// The first character within the box. firstChar()105 int firstChar() const { return m_firstChar == INT_MAX ? 0 : m_firstChar; } 106 /// The last character within the box. lastChar()107 int lastChar() const { return m_lastChar == INT_MIN ? 0 : m_lastChar; } 108 109 /// Sets the transformation matrix to applied to the box. setMatrix(QTransform x)110 void setMatrix(QTransform x) { m_matrix = x; } 111 112 /// The transformation matrix applied to the box. matrix()113 const QTransform& matrix() const { return m_matrix; } 114 115 // virtual void justify(const ParagraphStyle& style) {} 116 117 /// Returns the children of the box. boxes()118 QList<Box*>& boxes() { return m_boxes; } boxes()119 const QList<const Box*>& boxes() const { 120 return reinterpret_cast<const QList<const Box*> & > (m_boxes); 121 } 122 123 /// Returns the number of child boxes boxCount()124 int boxCount() const { return m_boxes.count(); } 125 126 /// Returns if current box contains any child boxes isEmpty()127 bool isEmpty() const { return m_boxes.isEmpty(); } 128 129 /// Renders the box and any boxes it contains, recursively. 130 virtual void render(TextLayoutPainter *p) const = 0; 131 132 /// Same as render() but handles text selection, for rendering on screen. 133 virtual void render(ScreenPainter *p, ITextContext *ctx) const = 0; 134 135 /// Draw selection if the the box selected drawSelection(ScreenPainter * p,ITextContext * ctx)136 virtual void drawSelection(ScreenPainter *p, ITextContext *ctx) const {} 137 138 /// Get natural ascent and descent. naturalAsc()139 virtual double naturalAsc() const { return m_naturalAscent; } naturalDescent()140 virtual double naturalDescent() const { return m_naturalDescent; } 141 142 /// return box type type()143 BoxType type() const { return m_type; } 144 145 protected: 146 BoxType m_type; 147 BoxDirection m_direction; 148 double m_x; 149 double m_y; 150 double m_width; 151 double m_descent; 152 double m_ascent; 153 QList<Box*> m_boxes; 154 int m_firstChar; 155 int m_lastChar; 156 QTransform m_matrix; 157 double m_naturalAscent; 158 double m_naturalDescent; 159 }; 160 161 162 class GroupBox: public Box 163 { 164 public: GroupBox(BoxDirection direction)165 GroupBox(BoxDirection direction) 166 { 167 m_type = T_Block; 168 m_direction = direction; 169 m_firstChar = INT_MAX; 170 m_lastChar = INT_MIN; 171 m_naturalWidth = m_naturalHeight = 0; 172 } 173 174 int pointToPosition(QPointF coord, const StoryText &story) const override; 175 QLineF positionToPoint(int pos, const StoryText& story) const override; 176 177 void render(TextLayoutPainter *p) const override; 178 void render(ScreenPainter *p, ITextContext *ctx) const override; 179 void drawSelection(ScreenPainter *p, ITextContext *ctx) const override; 180 naturalWidth()181 double naturalWidth() const override { return m_naturalWidth; } 182 double naturalHeight() const override; 183 184 // void justify(const ParagraphStyle& style); 185 186 /// Adds a new child to the box. 187 virtual void addBox(const Box* box); 188 /// Remove the child at i. 189 virtual void removeBox(int i); 190 191 protected: 192 double m_naturalWidth; 193 double m_naturalHeight; 194 195 private: 196 void update(); 197 }; 198 199 200 class LineBox: public GroupBox 201 { 202 public: LineBox()203 LineBox() 204 : GroupBox(D_Horizontal) 205 { 206 m_type = T_Line; 207 } 208 209 int pointToPosition(QPointF coord, const StoryText &story) const override; 210 QLineF positionToPoint(int pos, const StoryText& story) const override; 211 212 bool containsPoint(QPointF coord) const override; 213 214 void render(TextLayoutPainter *p) const override; 215 void render(ScreenPainter *p, ITextContext *ctx) const override; 216 void drawSelection(ScreenPainter *p, ITextContext *ctx) const override; 217 naturalWidth()218 double naturalWidth() const override{ return m_naturalWidth; } naturalHeight()219 double naturalHeight() const override{ return height(); } 220 221 // void justify(const ParagraphStyle& style); 222 223 void addBox(const Box* box) override; 224 void removeBox(int i) override; 225 226 protected: 227 virtual void drawBackGround(TextLayoutPainter *p) const; 228 virtual void update(); 229 }; 230 231 class PathLineBox: public LineBox 232 { 233 public: PathLineBox()234 PathLineBox() 235 { 236 m_type = T_PathLine; 237 } 238 239 protected: 240 void update() override; 241 void drawBackGround(TextLayoutPainter *p) const override; 242 }; 243 244 class GlyphBox: public Box 245 { 246 public: GlyphBox(const GlyphCluster & run)247 GlyphBox(const GlyphCluster& run) 248 : m_glyphRun(run) 249 , m_effects(run.style().effects()) 250 { 251 m_type = T_Glyph; 252 m_firstChar = run.firstChar(); 253 m_lastChar = run.lastChar(); 254 m_width = run.width(); 255 m_naturalAscent = run.ascent(); 256 m_naturalDescent = run.descent(); 257 } 258 259 int pointToPosition(QPointF coord, const StoryText &story) const override; 260 QLineF positionToPoint(int pos, const StoryText& story) const override; 261 262 void render(TextLayoutPainter *p) const override; 263 void render(ScreenPainter *p, ITextContext *ctx) const override; 264 void drawSelection(ScreenPainter *p, ITextContext *ctx) const override; 265 glyphRun()266 GlyphCluster glyphRun() const { return m_glyphRun; } 267 style()268 const CharStyle& style() const { return m_glyphRun.style(); } 269 270 protected: 271 GlyphCluster m_glyphRun; 272 const StyleFlag m_effects; 273 }; 274 275 class ObjectBox: public GlyphBox 276 { 277 public: ObjectBox(const GlyphCluster & run,ITextContext * ctx)278 ObjectBox(const GlyphCluster& run, ITextContext* ctx) 279 : GlyphBox(run) 280 , m_object(ctx->object(run.object())) 281 { 282 m_type = T_Object; 283 } 284 285 void render(TextLayoutPainter *p) const override; 286 void render(ScreenPainter*, ITextContext *ctx) const override; 287 288 private: 289 /* const */ PageItem* m_object; 290 }; 291 292 #endif // BOXES_H 293