File indexing completed on 2025-04-20 05:11:11
0001 // 0002 // C++ Interface: canvas_private 0003 // 0004 // Description: 0005 // 0006 // 0007 // Author: Alan Grimes <agrimes@speakeasy.net>, (C) 2008 0008 // 0009 // Copyright: See COPYING file that comes with this distribution 0010 // 0011 // 0012 0013 #ifndef CANVAS_PRIVATE_H 0014 #define CANVAS_PRIVATE_H 0015 0016 #include "canvasitems.h" 0017 #include "ktlq3polygonscanner.h" 0018 #include <QBitmap> 0019 #include <QImage> 0020 0021 class KtlQPolygonalProcessor 0022 { 0023 public: 0024 KtlQPolygonalProcessor(KtlQCanvas *c, const QPolygon &pa) 0025 : canvas(c) 0026 { 0027 QRect pixelbounds = pa.boundingRect(); 0028 bounds.setLeft(canvas->toChunkScaling(pixelbounds.left())); 0029 bounds.setRight(canvas->toChunkScaling(pixelbounds.right())); 0030 bounds.setTop(canvas->toChunkScaling(pixelbounds.top())); 0031 bounds.setBottom(canvas->toChunkScaling(pixelbounds.bottom())); 0032 // bitmap = QImage(bounds.width(),bounds.height(),1,2,QImage::LittleEndian); // 2018.09.07 - convert to non-deprecated 0033 bitmap = QImage(bounds.width(), bounds.height(), QImage::Format_MonoLSB); 0034 pnt = 0; 0035 bitmap.fill(0); 0036 } 0037 0038 inline void add(int x, int y) 0039 { 0040 if (pnt >= result.size()) { 0041 result.resize(pnt * 2 + 10); 0042 } 0043 result[pnt++] = QPoint(x + bounds.x(), y + bounds.y()); 0044 } 0045 0046 inline void addBits(int x1, int x2, uchar newbits, int xo, int yo) 0047 { 0048 for (int i = x1; i <= x2; i++) 0049 if (newbits & (1 << i)) 0050 add(xo + i, yo); 0051 } 0052 0053 void doSpans(int n, QPoint *pt, int *w) 0054 { 0055 for (int j = 0; j < n; j++) { 0056 int y = canvas->toChunkScaling(pt[j].y()) - bounds.y(); 0057 uchar *l = bitmap.scanLine(y); 0058 int x = pt[j].x(); 0059 int x1 = canvas->toChunkScaling(x) - bounds.x(); 0060 int x2 = canvas->toChunkScaling(x + w[j]) - bounds.x(); 0061 int x1q = x1 / 8; 0062 int x1r = x1 % 8; 0063 int x2q = x2 / 8; 0064 int x2r = x2 % 8; 0065 if (x1q == x2q) { 0066 uchar newbits = (~l[x1q]) & (((2 << (x2r - x1r)) - 1) << x1r); 0067 if (newbits) { 0068 addBits(x1r, x2r, newbits, x1q * 8, y); 0069 l[x1q] |= newbits; 0070 } 0071 } else { 0072 uchar newbits1 = (~l[x1q]) & (0xff << x1r); 0073 if (newbits1) { 0074 addBits(x1r, 7, newbits1, x1q * 8, y); 0075 l[x1q] |= newbits1; 0076 } 0077 for (int i = x1q + 1; i < x2q; i++) { 0078 if (l[i] != 0xff) { 0079 addBits(0, 7, ~l[i], i * 8, y); 0080 l[i] = 0xff; 0081 } 0082 } 0083 uchar newbits2 = (~l[x2q]) & (0xff >> (7 - x2r)); 0084 if (newbits2) { 0085 addBits(0, x2r, newbits2, x2q * 8, y); 0086 l[x2q] |= newbits2; 0087 } 0088 } 0089 } 0090 result.resize(pnt); 0091 } 0092 0093 QPolygon result; 0094 0095 private: 0096 int pnt; 0097 0098 KtlQCanvas *canvas; 0099 QRect bounds; 0100 QImage bitmap; 0101 }; 0102 0103 class KtlQCanvasViewData 0104 { 0105 public: 0106 KtlQCanvasViewData() 0107 : repaint_from_moving(false) 0108 { 0109 } 0110 QTransform xform; 0111 QTransform ixform; 0112 bool repaint_from_moving; 0113 }; 0114 0115 class KtlQCanvasClusterizer 0116 { 0117 public: 0118 KtlQCanvasClusterizer(int maxclusters); 0119 ~KtlQCanvasClusterizer(); 0120 0121 void add(int x, int y); // 1x1 rectangle (point) 0122 void add(int x, int y, int w, int h); 0123 void add(const QRect &rect); 0124 0125 void clear(); 0126 int clusters() 0127 { 0128 return count; 0129 } 0130 const QRect &operator[](int i); 0131 0132 private: 0133 QRect *cluster; 0134 int count; 0135 const int maxcl; 0136 }; 0137 0138 class KtlQCanvasItemPtr 0139 { 0140 public: 0141 KtlQCanvasItemPtr() 0142 : ptr(nullptr) 0143 { 0144 } 0145 KtlQCanvasItemPtr(KtlQCanvasItem *p) 0146 : ptr(p) 0147 { 0148 } 0149 0150 bool operator<=(const KtlQCanvasItemPtr &that) const 0151 { 0152 // Order same-z objects by identity. 0153 if (that.ptr->z() == ptr->z()) 0154 return that.ptr <= ptr; 0155 return that.ptr->z() <= ptr->z(); 0156 } 0157 0158 bool operator<(const KtlQCanvasItemPtr &that) const 0159 { 0160 // Order same-z objects by identity. 0161 if (that.ptr->z() == ptr->z()) 0162 return that.ptr < ptr; 0163 return that.ptr->z() < ptr->z(); 0164 } 0165 0166 bool operator>(const KtlQCanvasItemPtr &that) const 0167 { 0168 // Order same-z objects by identity. 0169 if (that.ptr->z() == ptr->z()) 0170 return that.ptr > ptr; 0171 return that.ptr->z() > ptr->z(); 0172 } 0173 0174 bool operator==(const KtlQCanvasItemPtr &that) const 0175 { 0176 return that.ptr == ptr; 0177 } 0178 0179 operator KtlQCanvasItem *() const 0180 { 0181 return ptr; 0182 } 0183 0184 private: 0185 KtlQCanvasItem *ptr; 0186 }; 0187 0188 class KtlQCanvasChunk 0189 { 0190 public: 0191 KtlQCanvasChunk() 0192 : changed(true) 0193 { 0194 } 0195 // Other code assumes lists are not deleted. Assignment is also 0196 // done on ChunkRecs. So don't add that sort of thing here. 0197 0198 void sort() 0199 { 0200 list.sort(); 0201 } 0202 0203 const KtlQCanvasItemList *listPtr() const 0204 { 0205 return &list; 0206 } 0207 0208 void add(KtlQCanvasItem *item) 0209 { 0210 list.prepend(item); 0211 changed = true; 0212 } 0213 0214 void remove(KtlQCanvasItem *item) 0215 { 0216 list.removeAll(item); 0217 changed = true; 0218 } 0219 0220 void change() 0221 { 0222 changed = true; 0223 } 0224 0225 bool hasChanged() const 0226 { 0227 return changed; 0228 } 0229 0230 bool takeChange() 0231 { 0232 bool y = changed; 0233 changed = false; 0234 return y; 0235 } 0236 0237 private: 0238 KtlQCanvasItemList list; 0239 bool changed; 0240 }; 0241 0242 class KtlQCanvasPolygonScanner : public KtlQ3PolygonScanner 0243 { 0244 KtlQPolygonalProcessor &processor; 0245 0246 public: 0247 KtlQCanvasPolygonScanner(KtlQPolygonalProcessor &p) 0248 : processor(p) 0249 { 0250 } 0251 void processSpans(int n, QPoint *point, int *width) override 0252 { 0253 processor.doSpans(n, point, width); 0254 } 0255 }; 0256 0257 // lesser-used data in canvas item, plus room for extension. 0258 // Be careful adding to this - check all usages. 0259 class KtlQCanvasItemExtra 0260 { 0261 KtlQCanvasItemExtra() /* : vx(0.0), vy(0.0) */ 0262 { 0263 } 0264 // double vx,vy; // 2017.10.01 - commented unused members 0265 friend class KtlQCanvasItem; 0266 }; 0267 0268 #endif