File indexing completed on 2024-04-14 05:36:56

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