The ZX Ecosystem v5.1.0;_GUI_v3.1.0
Loading...
Searching...
No Matches
ZXGraphics.h
Go to the documentation of this file.
1
2/* **************************************************************************/
24#ifndef ZXGRAPHICS
25#define ZXGRAPHICS
26
27#include <string>
28#include <cstdint>
29#include <type_traits>
30#include <limits>
31#include <memory>
32#include <utility>
33#include <functional>
39
40namespace zxeco
41{
42
43/* ***************************************************************************
44*
45* Coordinate system for the screen, both for pixels and characters.
46*
47*******************************************************************************/
48
93using PixelCoord = uint16_t;
94using CharCoord = uint16_t;
95
96using PixelDist = uint16_t;
97using CharDist = uint16_t;
98
99using IntDist = int16_t;
100
101using BorderCoord = int16_t;
102using BorderDist = uint16_t;
103
104
105constexpr PixelCoord kMaxPixelCoord = std::numeric_limits<PixelCoord>::max();
107
108constexpr CharCoord kMaxCharCoord = std::numeric_limits<CharCoord>::max();
110
111constexpr PixelDist kMaxPixelDist = std::numeric_limits<PixelDist>::max();
113
114constexpr CharDist kMaxCharDist = std::numeric_limits<CharDist>::max();
116
117constexpr IntDist kMinIntDist = std::numeric_limits<IntDist>::min();
119
120constexpr IntDist kMaxIntDist = std::numeric_limits<IntDist>::max();
122
123constexpr BorderCoord kMaxBorderCoord = std::numeric_limits<BorderCoord>::max();
125
126constexpr BorderDist kMaxBorderDist = std::numeric_limits<BorderDist>::max();
128
129
130/* ---------------------- PixelCoord functions ------------------ */
131
133
134constexpr CharCoord charOfPixelX(PixelCoord pc) noexcept
135 { return(pc / 8); }
136
138
139constexpr CharCoord charOfPixelY(PixelCoord pc) noexcept
140 { return(pc / 8); }
141
143
146 { return(pc & (~7)); }
147
149
152 { return(pc & (~7)); }
153
155
158constexpr unsigned char bitOfPixelX(PixelCoord pc) noexcept
159 { return(7 - (pc % 8)); }
160
161
162/* ---------------------- CharCoord functions ------------------ */
163
165
167constexpr PixelCoord pixelOfCharX(CharCoord cc) noexcept
168 { return(static_cast<PixelCoord>(cc) * 8); }
169
171
173constexpr PixelCoord pixelOfCharY(CharCoord cc) noexcept
174 { return(static_cast<PixelCoord>(cc) * 8); }
175
176
177/* ---------------------- PixelDist consts and functions ------------------ */
178
186constexpr PixelDist SCREENW = 256;
188constexpr PixelDist SCREENH = 192;
190constexpr BorderDist TOPBORDERH = 56;
192
195constexpr BorderDist LEFTBORDERW = 32;
203constexpr size_t BITMAPLEN = 6144;
205constexpr size_t ATTRMAPLEN = 768;
207constexpr size_t DISPLAYLEN = BITMAPLEN + ATTRMAPLEN;
209
213
216 { return(static_cast<PixelDist>(pc) * 8); }
217
218/* ---------------------- CharDist functions ------------------ */
219
221
224constexpr CharDist pixelDistToCharDist(PixelDist cc, bool toceil =true) noexcept
225 { return(static_cast<CharDist>(toceil ?
226 (cc % 8 > 0 ? (cc / 8 + 1) : (cc / 8)) :
227 (cc / 8))); }
228
233
236
241/*****************************************************************************
242*
243* Type trait base classes: CoordT, DistT
244* Type traits classes: CharCoordT, PixelCoordT, LongestCoordT,
245* CharDistT, PixelDistT, LongestDistT,
246* IntDistT, BorderCoordT, BorderDistT
247*
248*******************************************************************************/
249
251
254struct CoordT
255{
256};
257
259
262struct DistT
263{
264};
265
267struct CharCoordT: public CoordT
268{
269 using type = CharCoord;
270
271 static constexpr const char * name = "CharC";
272
274};
275
277struct PixelCoordT: public CoordT
278{
279 using type = PixelCoord;
280
281 static constexpr const char * name = "PixC";
282
284};
285
287struct CharDistT: public DistT
288{
289 using type = CharDist;
290
292
293 static constexpr const char * name = "CharD";
294
296};
297
299struct PixelDistT: public DistT
300{
301 using type = PixelDist;
302
304
305 static constexpr const char * name = "PixD";
306
308};
309
311
313{
314 using type = IntDist;
315
316 static constexpr const char * name = "IntD";
317
319};
320
322struct BorderCoordT: public CoordT
323{
325
326 static constexpr const char * name = "BorderC";
327
329};
330
332struct BorderDistT: public DistT
333{
334 using type = BorderDist;
335
337
338 static constexpr const char * name = "BorderD";
339
341};
342
346/*****************************************************************************
347*
348* Template class: Cursor
349* Class aliases: CharCursor, PixCursor, CharPixCursor, BorderCursor
350* Functions: getPixCursor, getCharPixCursor
351*
352*******************************************************************************/
353
355
357template <typename WRES, typename HRES>
359{
360 public:
361
362 using WidthType = WRES;
363 using HeightType = HRES;
364
365 typename WidthType::type x;
366 typename HeightType::type y;
367
368 static const Cursor & theZero(void) noexcept
370 { static const Cursor kz{0,0}; return(kz); }
371
372 static Cursor max(const Cursor & c0, const Cursor & c1) noexcept
374 { return(Cursor{(c0.x >= c1.x) && (c0.y >= c1.y) ? c0 : c1}); }
375
376
377 Cursor(typename WidthType::type xc,
378 typename HeightType::type yc): x{xc},y{yc} {}
380
383 Cursor(WidthType xc, HeightType yc): x{xc.value},y{yc.value} {}
385
387 void newRow(void) noexcept { ++y; x = 0; }
390 void newCol(void) noexcept { ++x; }
393 void incRow(void) noexcept { ++y; }
396 bool zero(void) const noexcept { return((x == 0) && (y == 0)); }
399 bool before(const Cursor & oth) const noexcept
401
402 { return((oth.y > y) || ((oth.x > x) && (oth.y == y))); }
404 bool rightBelow(const Cursor & oth) const noexcept
406
407 { return((y >= oth.y) && (x >= oth.x)); }
409 IntDist xDiff(const Cursor & oth) const noexcept
411 { return(static_cast<IntDist>(x - oth.x)); }
413 IntDist yDiff(const Cursor & oth) const noexcept
415 { return(static_cast<IntDist>(y - oth.y)); }
417 void addDiff(IntDist xdiff, IntDist ydiff) noexcept
419 { x = static_cast<typename WidthType::type>(
420 static_cast<IntDist>(x) + xdiff);
421 y = static_cast<typename HeightType::type>(
422 static_cast<IntDist>(y) + ydiff); }
424 bool operator==(const Cursor & oth) const noexcept
426 { return((oth.x == x) && (oth.y == y)); }
428 bool operator!=(const Cursor & oth) const noexcept
430 { return(!operator==(oth)); }
432 Cursor operator+(const Cursor & oth) const
434 { return(Cursor{static_cast<typename WidthType::type>(x + oth.x),
435 static_cast<typename HeightType::type>(y + oth.y)}); }
436
438 Cursor & operator+=(const Cursor & oth)
439 { *this = *this + oth; return(*this); }
441 Cursor operator-(const Cursor & oth) const
443 { if (this->rightBelow(oth))
444 return(Cursor{ static_cast<typename WidthType::type>(x - oth.x),
445 static_cast<typename HeightType::type>(y - oth.y)});
446 else RUNTIMEEXCEP("Substracting incorrect cursors"); }
447
449 Cursor & operator-=(const Cursor & oth)
450 { *this = *this - oth; return(*this); }
452 std::string to_string(bool withtype = true) const
454 { if (withtype)
455 return(std::string{"Cursor<"} + WidthType::name + "," +
456 HeightType::name +
457 ">(x: " + std::to_string(x) + ", y: " +
458 std::to_string(y) + ")");
459 return(std::string{"(x: "} + std::to_string(x) + ", y: " +
460 std::to_string(y) + ")"); }
461
462static_assert(std::is_base_of<CoordT,WRES>::value &&
463 std::is_base_of<CoordT,HRES>::value,
464 "WRES and HRES types in Cursor<> must be derived from CoordT");
465};
466
469
472
475
478
479
482 { return(PixCursor{pixelOfCharX(cc.x),pixelOfCharY(cc.y)}); }
483
486 { return(PixCursor{pixelOfCharX(cc.x),cc.y}); }
487
490 { return(CharPixCursor{cc.x,pixelOfCharY(cc.y)}); }
491
492
493/*****************************************************************************
494*
495* Template class: Area
496* Class aliases: CharArea, PixArea, CharPixArea, BorderArea
497* Function: getPixArea, getCharPixArea
498*
499*******************************************************************************/
500
502template <typename WRES, typename HRES>
503class Area
504{
505 public:
506
507 using WidthType = WRES;
508 using HeightType = HRES;
509 using CursorType = Cursor<typename WRES::coord_typeT,
510 typename HRES::coord_typeT>;
511
512 typename WidthType::type width;
513 typename HeightType::type height;
514
515 static const Area & theEmpty(void) noexcept
516 { static const Area kz{0,0}; return(kz); }
518
519
520 Area(typename WidthType::type w,
521 typename HeightType::type h): width{w},height{h} {}
523
526 Area(WidthType w, HeightType h): width{w.value},height{h.value} {}
528
530
532 Area(const CursorType & c0, const CursorType & c1)
533 { if (!c1.rightBelow(c0)) RUNTIMEEXCEP("Invalid corners for area");
534 width = c1.x - c0.x + 1; height = c1.y - c0.y + 1; }
536 bool empty(void) const noexcept { return((width == 0) || (height == 0)); }
539 size_t area(void) const noexcept
541 { return(static_cast<size_t>(width) * static_cast<size_t>(height)); }
543 bool containedInto(const Area & oth) const noexcept
545 { return((width <= oth.width) && (height <= oth.height)); }
547 Area operator+(const Area & oth) const noexcept
549 { return(Area{static_cast<typename WidthType::type>(width + oth.width),
550 static_cast<typename HeightType::type>(height +oth.height)
551 }); }
553 Area & operator+=(const Area & oth) noexcept
555 { width += oth.width; height += oth.height; return(*this); }
557 Area operator-(const Area & oth) const
559 { if (!oth.containedInto(*this))
560 RUNTIMEEXCEP("Cannot substract larger area");
561 return(Area{static_cast<typename WidthType::type>(width - oth.width),
562 static_cast<typename HeightType::type>(height -oth.height)
563 }); }
564
566 Area & operator-=(const Area & oth)
567 { if (!oth.containedInto(*this))
568 RUNTIMEEXCEP("Cannot substract larger area");
569 width -= oth.width; height -= oth.height; return(*this); }
571 Area operator*(const Area & oth) const
573 { return(Area{std::min(width,oth.width),std::min(height,oth.height)}); }
574
576 Area & operator*=(const Area & oth)
577 { width = std::min(width,oth.width);
578 height = std::min(height,oth.height); return(*this); }
580 bool operator==(const Area & oth) const noexcept
582 { return((width == oth.width) && (height == oth.height)); }
584 bool operator!=(const Area & oth) const noexcept
586 { return(!operator==(oth)); }
588 std::string to_string(bool withtype = true) const
590 { if (withtype)
591 return(std::string{"Area<"} + WidthType::name + "," +
592 HeightType::name +
593 ">[w: " + std::to_string((unsigned)width) + ", h: " +
594 std::to_string((unsigned)height) + "]");
595 return(std::string{"[w: "} +
596 std::to_string((unsigned)width) + ", h: " +
597 std::to_string((unsigned)height) + "]"); }
598
599static_assert(std::is_base_of<DistT,WRES>::value &&
600 std::is_base_of<DistT,HRES>::value,
601 "WRES and HRES types in Area<> must be derived from DistT");
602};
603
606
609
612
615
616
618inline PixArea getPixArea(const CharArea & cc)
619 { return(PixArea{charDistToPixelDist(cc.width),
621
624 { return(PixArea{charDistToPixelDist(cc.width),cc.height}); }
625
628 { return(CharPixArea{cc.width,charDistToPixelDist(cc.height)}); }
629
630
631/*****************************************************************************
632*
633* Template class: Rect
634* Class aliases: CharRect, PixRect, BorderRect
635* Function: getPixRect, getCharPixRect
636*
637*******************************************************************************/
638
640
642template <typename WRES, typename HRES>
643struct Rect
644{
645 using cursor_type = Cursor<typename WRES::coord_typeT,
646 typename HRES::coord_typeT>;
648
651
652 static const Rect & theEmpty(void) noexcept
653 { static const Rect kz{cursor_type::theZero(),
654 area_type::theEmpty()}; return(kz); }
656
657
658 Rect(const cursor_type & c = cursor_type{0,0},
659 const area_type & a = area_type{0,0}): corner{c},area{a} {}
661
662 bool empty(void) const noexcept { return(area.empty()); }
664
665 bool contains(const cursor_type & cur) const noexcept;
667
668 cursor_type bottomRight(void) const noexcept
670 { return(cursor_type{static_cast<typename WRES::coord_typeT::type>(
671 corner.x + area.width - 1),
672 static_cast<typename HRES::coord_typeT::type>(
673 corner.y + area.height - 1)}); }
674
675 bool applyConstrainedDiffs(IntDist & xdiff, IntDist & ydiff,
676 const Rect & oth) noexcept;
678
681 Rect compose(const Rect & reloth) const
683
688 { return(Rect{corner + reloth.corner,
689 reloth.area}); }
690
691 Rect subRect(const cursor_type & reltopleft) const
693 { return(Rect{corner + reltopleft,
694 {static_cast<CharDist>(area.width - reltopleft.x),
695 static_cast<CharDist>(area.height - reltopleft.y)}}); }
696
697 Rect intersect(const Rect & oth) const noexcept;
699
702 Rect align_area(const area_type & areaneeded,
703 char horalign, char vertalign) const;
705
712 bool operator==(const Rect & oth) const noexcept
714 { return((corner == oth.corner) && (area == oth.area)); }
715
716 bool operator!=(const Rect & oth) const noexcept
718 { return(!operator==(oth)); }
719
720 std::string to_string(bool withtype = true) const
722 { if (withtype)
723 return(std::string{"Rect<"} + WRES::name + "," + HRES::name +
724 ">{" + corner.to_string() + "; " +
725 area.to_string() + "}");
726 else return(std::string{"{"} + corner.to_string(false) + "; " +
727 area.to_string(false) + "}"); }
728
729static_assert(std::is_base_of<DistT,WRES>::value &&
730 std::is_base_of<DistT,HRES>::value,
731 "WRES and HRES types in Rect<> must be derived from DistT");
732};
733
736
739
742
745
746
748inline PixRect getPixRect(const CharRect & cc)
749 { return(PixRect{getPixCursor(cc.corner),getPixArea(cc.area)}); }
750
753 { return(PixRect{getPixCursor(cc.corner),getPixArea(cc.area)}); }
754
758 getCharPixArea(cc.area)}); }
759
760
761/*****************************************************************************
762*
763* Classes: DoubleArea, DoubleRect
764*
765*******************************************************************************/
766
769{
770 public:
771
774
775 /* -------------- Constructors -------------- */
778 DoubleArea(const CharArea & area = CharArea::theEmpty()):chararea{area},
779 pixarea{getPixArea(area)}
781 {}
782
783 DoubleArea(const CharArea & carea, const PixArea & parea): chararea{carea},
784 pixarea{parea}
786 {}
787
791 std::string to_string(void) const
792 { return("DoubleArea: " + chararea.to_string() + " | " +
793 pixarea.to_string()); }
794};
795
796
799{
800 public:
801
804
805 /* -------------- Constructors -------------- */
808 DoubleRect(const CharRect & rect = CharRect::theEmpty()):charrect{rect},
809 pixrect{getPixRect(rect)}
811 {}
812
813 DoubleRect(const CharRect & crect, const PixRect & prect): charrect{crect},
814 pixrect{prect}
816 {}
817
820 std::string to_string(void) const
821 { return("DoubleRect: " + charrect.to_string() + " | " +
822 pixrect.to_string()); }
823};
824
825
826/*****************************************************************************
827*
828* Base Abstract Class: LinearGraphic
829*
830*******************************************************************************/
831
834{
835 public:
836
837 /* -------------- Types, consts, etc. -------------- */
838
841 enum class GraphOp: unsigned char {
842 COPY,
843 INV,
844 OR,
845 INVOR,
846 AND,
847 INVAND,
848 XOR,
849 INVXOR
850 };
851
852
853 /* -------------- Class methods ----------- */
854
855 template <LinearGraphic::GraphOp op>
856 static constexpr uint8_t doGraphOp(uint8_t b0, uint8_t b1) noexcept;
858 /* Constexpr's are inherently inline.
859 (Specializations of this template are at the end of the class)*/
860
861
862 /* -------------- Constructors -------------- */
863
866
867 LinearGraphic(size_t s);
869
871 LinearGraphic(size_t s, uint8_t b);
873
874 LinearGraphic(uint8_t * bs, size_t s);
876
878 LinearGraphic(LinearGraphic & oth, size_t firstoff,
879 size_t chunksize, size_t gap, size_t numchunks);
881
890 LinearGraphic(const LinearGraphic &) = delete;
891 LinearGraphic & operator=(const LinearGraphic &) = delete;
893 LinearGraphic & operator=(LinearGraphic &&og);
894
895 virtual ~LinearGraphic(void);
896
897
898 /* -------------- Methods -------------- */
899
900 bool external(void) const noexcept { return(external_); }
902
903 bool owner(void) const noexcept { return(owner_); }
905
908 size_t size(void) const noexcept { return(s_); }
910
915 bool oneByte(void) const noexcept { return(onebyte_); }
917
918 uint8_t getByte(size_t offset) const;
920
921 uint8_t getByteUnsafe(size_t offset) const noexcept;
923
924 uint8_t * getAllBytes(void);
926
927 void setByte(size_t offset, uint8_t b);
929
932 void setByteUnsafe(size_t offset, uint8_t b) noexcept;
936 void setAllBytes(uint8_t b) noexcept;
940 void merge(size_t destoffset, const LinearGraphic & oth, size_t origoffset,
941 size_t howmany, GraphOp op = GraphOp::COPY);
943
946 void mergeUnsafe(size_t destoffset,
947 const LinearGraphic & oth, size_t origoffset,
948 size_t howmany, GraphOp op = GraphOp::COPY);
950
953 int compare(const LinearGraphic & oth, bool withinv = false) const noexcept;
955
960 size_t similarity(const LinearGraphic & oth) const noexcept;
962
967 std::string to_string(void) const;
969
970
971 protected:
972
973 bool owner_;
974 size_t s_;
975
976 void clear(void);
977 void reset(void);
978 void moveFrom(LinearGraphic && og);
979
980 private:
981
982 bool external_;
983 bool onebyte_;
984 union {
985 uint8_t thebyte; // if non-external, one-byte
986 uint8_t * bytes; // if non-external, non-one-byte
987 struct {
988 LinearGraphic * other;
989 size_t firstoff;
990 size_t chunksize;
991 size_t gap;
992 size_t numchunks;
993 } external; // if external
994 } data_;
995};
996
997
998/*****************************************************************************
999*
1000* Template Class: DimsGraphic
1001* Function: graphicDimensionsTooLarge
1002*
1003*******************************************************************************/
1004
1006
1007template <typename HEIGHTRESOL>
1009{
1010 public:
1011
1015
1016
1017 /* -------------- Attributes -------------- */
1018
1020
1021
1022 /* -------------- Constructors -------------- */
1023
1026
1027 DimsGraphic(const AreaType & a): LinearGraphic{sizeForDimensions(a)},
1028 dims{a} {}
1030
1031 DimsGraphic(const AreaType & a, uint8_t b):
1032 LinearGraphic{sizeForDimensions(a),b},
1033 dims{a} {}
1035
1036 DimsGraphic(uint8_t *bs, const AreaType & a):
1037 LinearGraphic{bs,sizeForDimensions(a)},
1038 dims{a} {}
1040
1041 DimsGraphic(DimsGraphic & g, const RectType & region, bool copy = true);
1043
1052 DimsGraphic(DimsGraphic && oth): dims{0,0} { moveFrom(std::move(oth)); }
1054
1057 { if (this != &oth) { LinearGraphic::clear(); moveFrom(std::move(oth));}
1058 return(*this); }
1059
1060 /* -------------- Methods -------------- */
1061
1062 size_t offset(const CursorType & pos) const;
1064
1066 CursorType coords(size_t offset) const;
1068
1071
1072 uint8_t getByte(const CursorType & pos) const
1074 { return(LinearGraphic::getByteUnsafe(offset(pos))); }
1075
1078
1079 void setByte(const CursorType & pos, uint8_t b)
1081
1084
1085 void merge(const DimsGraphic & oth, const CursorType & pos,
1086 GraphOp mode = GraphOp::COPY);
1088
1092
1104 typename HEIGHTRESOL::type scrollUp(typename HEIGHTRESOL::type howmany,
1105 typename HEIGHTRESOL::type upperrow,
1106 uint8_t fillb)
1107 { return(scrollUpRegion({{0,0},dims},howmany,upperrow,fillb)); }
1108
1109 std::string to_string(void) const;
1111
1112
1113 private:
1114
1115 static size_t sizeForDimensions(const AreaType & a)
1116 { return(static_cast<size_t>(a.width) * static_cast<size_t>(a.height));}
1117
1118 void moveFrom(DimsGraphic && og)
1119 { // requires LinearGraphic::clear before if this contains anything
1120 dims = og.dims;
1121 LinearGraphic::moveFrom(std::move(og));
1122 og.dims = {0,0};
1123 }
1124
1125 typename HEIGHTRESOL::type scrollUpRegion(const RectType & region,
1126 typename HEIGHTRESOL::type howmany,
1127 typename HEIGHTRESOL::type upperrow,
1128 uint8_t fillb);
1129
1130static_assert(std::is_base_of<DistT,HEIGHTRESOL>::value,
1131 "HEIGHTRESOL type in DimsGraphic<> must be derived from DistT");
1132
1133};
1134
1135
1136template <typename WIDTHRESOL, typename HEIGHTRESOL>
1137inline bool graphicDimensionsTooLarge(unsigned sx, unsigned sy) noexcept
1141
1142
1143/*****************************************************************************
1144*
1145* Class: Bitmap
1146*
1147*******************************************************************************/
1148
1150class Bitmap: public DimsGraphic<PixelDistT>
1151{
1152 public:
1153
1155
1156
1157 /* -------------- Constructors -------------- */
1158
1159 using BaseGr::BaseGr;
1161
1162 Bitmap(DesktopInterface & desktop, const std::string & pngfile);
1164
1169 Bitmap(uint8_t ascii, uint8_t * chartable = nullptr);
1171
1190 /* -------------- Methods -------------- */
1191
1192 using BaseGr::merge;
1194
1195 void merge(const Bitmap & oth, const PixCursor & pos,
1196 GraphOp mode = GraphOp::COPY);
1198
1207 std::string to_string(void) const { return(BaseGr::to_string()); }
1209
1210};
1211
1212
1213/*****************************************************************************
1214*
1215* Class: Attrmap
1216*
1217*******************************************************************************/
1218
1220class Attrmap: public DimsGraphic<CharDistT>
1221{
1222 public:
1223
1225
1226 /* -------------- Constructors -------------- */
1227
1228 using BaseGr::BaseGr;
1230
1231
1232 /* -------------- Methods -------------- */
1233
1234 void swapPaperInk(void);
1236
1237 std::string to_string(void) const { return(BaseGr::to_string()); }
1239};
1240
1241
1242/*****************************************************************************
1243*
1244* Class: DoubleGraphic
1245*
1246*******************************************************************************/
1247
1250{
1251 public:
1252
1253 /* -------------- Types, consts, etc. -------------- */
1254
1259 Dither
1261 };
1262
1265 None,
1266 FixedPattern,
1267 Noise
1268 };
1269
1271 using NumDithLevels = uint8_t;
1272
1275 {
1278 struct {
1280 struct {
1290 };
1291
1292
1293 /* -------------- Members -------------- */
1294
1295 Bitmap bitmap;
1296 Attrmap attrmap;
1297
1298
1299 /* -------------- Constructors -------------- */
1300
1302 bitmap{getCharPixArea(dims)},
1303 attrmap{dims} {}
1305
1308 DoubleGraphic(uint8_t * bs, uint8_t * as, const CharArea & a):
1309 bitmap{bs,getCharPixArea(a)},
1310 attrmap{as,a} {}
1313 DoubleGraphic(DoubleGraphic & g, const CharRect & region, bool copy = true):
1314 bitmap{g.bitmap,getCharPixRect(region),copy},
1315 attrmap{g.attrmap,region,copy} {}
1317
1325 DoubleGraphic(DesktopInterface & desktop, const std::string & pngfile,
1326 const PNGConversionParms & parms =
1330
1333 DoubleGraphic(const DoubleGraphic &) = delete;
1334 DoubleGraphic & operator=(const DoubleGraphic &) = delete;
1335 DoubleGraphic(DoubleGraphic && oth):DoubleGraphic{CharArea{0,0}}
1336 { moveFrom(std::move(oth)); }
1337 DoubleGraphic & operator=(DoubleGraphic && oth)
1338 { if (this != &oth) moveFrom(std::move(oth)); return(*this); }
1339
1340 virtual ~DoubleGraphic(void);
1341
1342
1343 /* -------------- Methods -------------- */
1344
1348 void merge(const DoubleGraphic & oth, const CharCursor & pos,
1350 { bitmap.merge(oth.bitmap,getCharPixCursor(pos));
1351 attrmap.merge(oth.attrmap,pos); }
1352
1354
1355 void savePNG(DesktopInterface & desktop, const std::string & pngfile);
1356
1357 std::string to_string(void) const
1358 { return("Bitmap: " + bitmap.to_string() +
1359 "; Attrmap: " + attrmap.to_string()); }
1361
1362 private:
1363
1364 using ColCountInCell = uint8_t; // max == 64
1365 using ColFreq = std::pair<RGBPalette::Index,ColCountInCell>;
1366 using ZXColorDecisor = std::function<
1367 std::pair<BrightColor,BrightColor>(const PNGConversionParms &,
1368 ColFreq *,
1369 size_t) >;
1371
1372 using ZXBitmapDecisor = std::function<
1373 bool(const PNGConversionParms &,
1374 const RasterCursor<1,1> &,
1375 const RGBColor &, const std::pair<BrightColor,BrightColor>) >;
1377
1381 class DitheringSystem
1382 {
1383 public:
1384
1385 using DitherLevel = NumDithLevels;
1386
1387 static constexpr NumDithLevels kMinDiths = 3; // 2 pure + 1 dithered
1388 static constexpr NumDithLevels kMaxDiths = 101; // 2 pure + 99 dithd
1389
1390 static constexpr RGBPalette::Size kNumPureColors =
1392 static constexpr RGBPalette::Size kNumColorsButBright =
1394 static constexpr RGBPalette::Size kClusterSizeButBright =
1395 (kNumColorsButBright - 1) *
1396 kNumColorsButBright /
1397 2; // explanations in .cpp
1398 static constexpr RGBPalette::Size kClusterSize =
1399 kClusterSizeButBright * 2;
1401
1402 class Color
1403 {
1404 public:
1405
1406 friend DitheringSystem; // for DitheringSystem to be the factory
1407
1408 RGBPalette::Index indexInPal(void) const noexcept
1409 { return(palcolor_); }
1410
1411 RGBColor rgbColor(void) const;
1412
1413 RGBPalette::Index firstExtreme(void) const noexcept
1414 { return(c0_); } // in ZX palette
1415 RGBPalette::Index secondExtreme(void) const noexcept
1416 { return(c1_); } // in ZX palette
1417 DitherLevel ditherLevel(void) const noexcept { return(l_); }
1418
1419 bool notDithered(void) const noexcept
1420 { return((l_ == 0) || (l_ == dsys_->maxDithLevel())); }
1421
1422 bool equalExtremesOrder(const Color & oc) const noexcept
1423 { checkSameLevs(oc); return((oc.c0_ == c0_) && (oc.c1_ ==c1_));}
1424
1425 bool equalExtremesNotOrder(const Color & oc) const noexcept
1426 { checkSameLevs(oc); return((oc.c0_ == c1_) && (oc.c1_ ==c0_));}
1427
1428 bool equalExtremes(const Color & oc) const noexcept
1429 { checkSameLevs(oc);
1430 return(equalExtremesOrder(oc) || equalExtremesNotOrder(oc)); }
1431
1432 Color makeCompatibleWith(const Color & oc) const noexcept;
1433
1434 std::string to_string(void) const;
1435
1436 private:
1437
1438 const DitheringSystem * dsys_;
1439 RGBPalette::Index palcolor_; // index of the color in dithered pal
1440 RGBPalette::Index c0_,c1_; // extreme colors of the color in ZX pal
1441 DitherLevel l_;
1446 Color(RGBPalette::Index palind, const DitheringSystem & dithsys);
1447 Color(const RGBColor & rgb, const DitheringSystem & dithsys);
1448
1449 void checkSameLevs(const Color & oth) const;
1450 int closestLevel(const Color &oc) const;
1451 };
1452
1453
1454 DitheringSystem(NumDithLevels nlvs): numlvs_{nlvs}
1455 { if ((nlvs < kMinDiths) || (nlvs > kMaxDiths))
1456 RUNTIMEEXCEP("Out of range number of dithering levels"); }
1457 DitheringSystem(const DitheringSystem &) = delete;
1458 DitheringSystem(DitheringSystem &&) = delete;
1459 DitheringSystem & operator=(const DitheringSystem &) = delete;
1460 DitheringSystem & operator=(DitheringSystem &&) = delete;
1461
1462 constexpr NumDithLevels numDithLevels(void) const noexcept
1463 { return(numlvs_); }
1464
1465 constexpr NumDithLevels maxDithLevel(void) const noexcept
1466 { return(numlvs_ - 1); }
1467
1468 constexpr DitherLevel inverseDithLevel(DitherLevel dl) const noexcept
1469 { return(maxDithLevel() - dl); }
1470
1471 constexpr RGBPalette::Size numClusters(void) const noexcept
1472 { return(numlvs_ - 2); }
1473
1474 constexpr RGBPalette::Size totalColors(void) const noexcept
1475 { return(kNumPureColors + // pure colors
1476 kClusterSize * numClusters()); } // clusters of dithered
1477
1478 double dithLevDegree(DitherLevel dl) const;
1479
1480 const RGBPalette & ditheredPalette(void) const noexcept;
1481
1482 Color deployColor(const RGBColor & rgb) const
1483 { return(Color{rgb,*this}); }
1484
1485 Color deployColor(RGBPalette::Index palind) const
1486 { return(Color(palind,*this)); }
1487
1488
1489 private: // DitheringSystem
1490
1491 static RGBColor rgbOfDitheredColor(const RGBColor & rgb0,
1492 const RGBColor & rgb1,
1493 double ditherdegree);
1494
1495
1496 NumDithLevels numlvs_;
1497 };
1498
1499
1500 template <typename ColorIndex>
1501 static void fillFreqs(const PalettizedImage<ColorIndex> & img,
1502 const RasterCursor<8,8> & cl,
1503 ColFreq * freqs)
1506 {
1507 for (RGBPalette::Index f = 0; f < img.palette().numColors(); ++f)
1508 freqs[f] = std::make_pair(f,0);
1509 auto curpix = cl.subCursor(); // to scan that CELL at pixel resol.
1510 do ++(freqs[img.pixel(curpix)].second);
1511 while (curpix.forward());
1512
1513 std::sort(freqs,freqs + img.palette().numColors(),
1514 [](const ColFreq & lhs, const ColFreq & rhs) -> bool
1515 { return(lhs.second > rhs.second); });
1516 }
1517
1518 static void reduceColors(const RGBPalette & pal, ColFreq * freqs);
1519
1520 static void fillGraphicFromZXNoClash(
1521 const PalettizedImage<uint8_t> & palimg,
1522 const PNGConversionParms & parms,
1523 const ZXColorDecisor & zxcoldec,
1524 const ZXBitmapDecisor & zxbmdec,
1525 Bitmap & bitmap, Attrmap & attrmap);
1526
1527 void fillGraphicFromRGB_ToNearestPlain(const RGBImage & rgbimg,
1528 const PNGConversionParms & parms,
1529 Bitmap & bitmap, Attrmap & attrmap);
1530 void fillGraphicFromRGB_Dither(const RGBImage & rgbimg,
1531 const PNGConversionParms & parms,
1532 Bitmap & bitmap, Attrmap & attrmap);
1533
1534
1535 void moveFrom(DoubleGraphic && oth)
1536 { bitmap = std::move(oth.bitmap); attrmap = std::move(oth.attrmap); }
1537};
1538
1539
1540
1541
1542
1543/*============================================================================
1544
1545 TEMPLATE IMPLEMENTATIONS
1546
1547==============================================================================*/
1548
1549
1550/*****************************************************************************
1551*
1552* Template class: Rect
1553*
1554*******************************************************************************/
1555
1556template <typename WRES, typename HRES>
1557bool Rect<WRES,HRES>::contains(const cursor_type & cur) const noexcept
1558{
1559 if (!cur.rightBelow(corner)) return(false);
1560 return(area_type{corner,cur}.containedInto(area));
1561}
1562
1563template <typename WRES, typename HRES>
1565 const Rect & oth) noexcept
1566{
1567 auto oldx = corner.x;
1568 auto oldy = corner.y;
1569 auto newx = static_cast<CharCoord>(static_cast<IntDist>(corner.x) + xdiff);
1570 auto newy = static_cast<CharCoord>(static_cast<IntDist>(corner.y) + ydiff);
1571 if ((xdiff < 0) &&
1572 (static_cast<CharCoord>(-xdiff) > corner.x))
1573 newx = 0;
1574 if ((ydiff < 0) &&
1575 (static_cast<CharCoord>(-ydiff) > corner.y))
1576 newy = 0;
1577 if (static_cast<int>(corner.x) + static_cast<int>(xdiff) +
1578 static_cast<int>(area.width) > oth.corner.x + oth.area.width)
1579 newx =
1580 static_cast<CharCoord>(oth.corner.x + oth.area.width - area.width);
1581 if (static_cast<int>(corner.y) + static_cast<int>(ydiff) +
1582 static_cast<int>(area.height) > oth.corner.y + oth.area.height)
1583 newy =
1584 static_cast<CharCoord>(oth.corner.y + oth.area.height -area.height);
1585 corner.x = newx;
1586 corner.y = newy;
1587 xdiff = static_cast<IntDist>(newx) - static_cast<IntDist>(oldx);
1588 ydiff = static_cast<IntDist>(newy) - static_cast<IntDist>(oldy);
1589 return((newx != oldx) || (newy != oldy));
1590}
1591
1592template <typename WRES, typename HRES>
1594{
1595 using WCoordType = typename WRES::coord_typeT::type;
1596 using HCoordType = typename HRES::coord_typeT::type;
1597 using WDistType = typename WRES::type;
1598 using HDistType = typename HRES::type;
1599
1600 Rect res; // empty
1601 if ((!empty()) && (!oth.empty()))
1602 {
1603 auto myxint = Interval<WCoordType>{corner.x,
1604 static_cast<WCoordType>(
1605 corner.x + area.width - 1)};
1606 auto myyint = Interval<HCoordType>{corner.y,
1607 static_cast<HCoordType>(
1608 corner.y + area.height - 1)};
1609 auto othxint = Interval<WCoordType>{oth.corner.x,
1610 static_cast<WCoordType>(
1611 oth.corner.x + oth.area.width -1)};
1612 auto othyint = Interval<HCoordType>{oth.corner.y,
1613 static_cast<HCoordType>(
1614 oth.corner.y + oth.area.height-1)};
1615 auto intersx = myxint.intersect(othxint);
1616 auto intersy = myyint.intersect(othyint);
1617 if ((!intersx.empty()) && (!intersy.empty()))
1618 {
1619 res.corner = {intersx.minimum(), intersy.minimum()};
1620 res.area = {static_cast<WDistType>(intersx.width() + 1),
1621 static_cast<HDistType>(intersy.width() + 1)};
1622 }
1623 }
1624 return(res);
1625}
1626
1627template <typename WRES, typename HRES>
1629 char horalign, char vertalign) const
1630{
1631 if (!areaneeded.containedInto(area))
1632 RUNTIMEEXCEP("Cannot align needed area: greater than available zone");
1633 cursor_type cur = cursor_type::theZero();
1634 if (area.width > areaneeded.width)
1635 { // it has spare room horizontally
1636 switch (horalign)
1637 {
1638 case 'C':
1639 {
1640 cur.x = (area.width - areaneeded.width) / 2;
1641 break;
1642 }
1643 case 'R':
1644 {
1645 cur.x = area.width - areaneeded.width;
1646 break;
1647 }
1648 }
1649 }
1650 if (area.height > areaneeded.height)
1651 { // it has spare room vertically
1652 switch (vertalign)
1653 {
1654 case 'M':
1655 {
1656 cur.y = (area.height - areaneeded.height) / 2;
1657 break;
1658 }
1659 case 'B':
1660 {
1661 cur.y = area.height - areaneeded.height;
1662 break;
1663 }
1664 }
1665 }
1666 return(Rect{corner + cur,areaneeded});
1667}
1668
1669
1670
1671/*****************************************************************************
1672*
1673* LinearGraphic
1674*
1675*******************************************************************************/
1676
1677template<>
1678constexpr uint8_t LinearGraphic::doGraphOp<LinearGraphic::GraphOp::COPY>(
1679 uint8_t b0,
1680 uint8_t b1) noexcept
1681 { return(b1); }
1682
1683template<>
1684constexpr uint8_t LinearGraphic::doGraphOp<LinearGraphic::GraphOp::INV>(
1685 uint8_t b0,
1686 uint8_t b1) noexcept
1687 { return(~b1); }
1688
1689template<>
1690constexpr uint8_t LinearGraphic::doGraphOp<LinearGraphic::GraphOp::OR>(
1691 uint8_t b0,
1692 uint8_t b1) noexcept
1693 { return(b1 | b0); }
1694
1695template<>
1696constexpr uint8_t LinearGraphic::doGraphOp<LinearGraphic::GraphOp::INVOR>(
1697 uint8_t b0,
1698 uint8_t b1) noexcept
1699 { return((~b1) | b0); }
1700
1701template<>
1702constexpr uint8_t LinearGraphic::doGraphOp<LinearGraphic::GraphOp::AND>(
1703 uint8_t b0,
1704 uint8_t b1) noexcept
1705 { return(b1 & b0); }
1706
1707template<>
1708constexpr uint8_t LinearGraphic::doGraphOp<LinearGraphic::GraphOp::INVAND>(
1709 uint8_t b0,
1710 uint8_t b1) noexcept
1711 { return((~b1) & b0); }
1712
1713template<>
1714constexpr uint8_t LinearGraphic::doGraphOp<LinearGraphic::GraphOp::XOR>(
1715 uint8_t b0,
1716 uint8_t b1) noexcept
1717 { return(b1 ^ b0); }
1718
1719template<>
1720constexpr uint8_t LinearGraphic::doGraphOp<LinearGraphic::GraphOp::INVXOR>(
1721 uint8_t b0,
1722 uint8_t b1) noexcept
1723 { return((~b1) ^ b0); }
1724
1725
1726/*****************************************************************************
1727*
1728* Template Class: DimsGraphic
1729*
1730*******************************************************************************/
1731
1732template <typename HEIGHTRESOL>
1733typename HEIGHTRESOL::type DimsGraphic<HEIGHTRESOL>::scrollUpRegion(
1734 const RectType & region,
1735 typename HEIGHTRESOL::type howmany,
1736 typename HEIGHTRESOL::type upperrow,
1737 uint8_t fillb)
1738// upperrow is relative to region (0 for top)
1739{
1740 if ((howmany == 0) || (howmany >= region.area.height) ||
1741 (upperrow >= region.area.height) || oneByte())
1742 return(upperrow);
1743
1744 if (upperrow < howmany)
1745 upperrow = static_cast<typename HEIGHTRESOL::type>(howmany);
1746 // The rest of rows dissapear, not move.
1747 // From now on, upperrow >= howmany
1748
1749 const typename HEIGHTRESOL::type firstoverwritten = upperrow - howmany;
1750 const typename HEIGHTRESOL::type rowstomove = region.area.height - upperrow;
1751 size_t offsetfirstrow = // in the container graphic
1752 static_cast<size_t>(upperrow + region.corner.y) *
1753 static_cast<size_t>(dims.width) +
1754 static_cast<size_t>(region.corner.x);
1755 size_t offsetfirstoverwritten =
1756 static_cast<size_t>(firstoverwritten + region.corner.y) *
1757 static_cast<size_t>(dims.width) +
1758 static_cast<size_t>(region.corner.x);
1759
1760 // scroll up
1761 for (typename HEIGHTRESOL::type f = 0; f < rowstomove; ++f)
1762 {
1763 LinearGraphic::mergeUnsafe(offsetfirstoverwritten,*this,offsetfirstrow,
1764 region.area.width);
1765 offsetfirstrow += dims.width;
1766 offsetfirstoverwritten += dims.width;
1767 }
1768
1769 // clear last rows
1770 offsetfirstrow = static_cast<size_t>(region.area.height - 1 +
1771 region.corner.y) *
1772 static_cast<size_t>(dims.width) +
1773 static_cast<size_t>(region.corner.x);
1774 const LinearGraphic blankline{region.area.width,fillb};
1775 for (typename HEIGHTRESOL::type f = 0; f < howmany; ++f)
1776 {
1777 LinearGraphic::mergeUnsafe(offsetfirstrow,blankline,0,
1778 region.area.width);
1779 offsetfirstrow -= dims.width;
1780 }
1781
1782 return(upperrow);
1783}
1784
1785template <typename HEIGHTRESOL>
1787 bool copy): DimsGraphic{{0,0},54}
1788{
1789 if ((g.dims.width == 0) || (g.dims.height == 0))
1790 RUNTIMEEXCEP("Cannot construct empty DimsGraphic from another "
1791 "DimsGraphic; g.width: " + std::to_string(g.dims.width) +
1792 ", g.height: " + std::to_string(g.dims.height) +
1793 "; g: " + g.to_string());
1794
1795 if ((region.corner.x >= g.dims.width) ||
1796 (region.corner.y >= g.dims.height)) return; // all outside: empty result
1797
1798 RectType reg = region;
1799 if (region.area.empty())
1800 {
1801 reg.area.width = g.dims.width - region.corner.x;
1802 reg.area.height = g.dims.height - region.corner.y;
1803 }
1804
1805 auto w = std::min(reg.area.width,
1806 static_cast<CharDist>(
1807 g.dims.width - reg.corner.x));
1808 auto h = std::min(reg.area.height,
1809 static_cast<
1810 typename HEIGHTRESOL::coord_typeT::type>(
1811 g.dims.height - reg.corner.y));
1812
1813 if (copy)
1814 {
1815 // copy from G to this
1816 size_t offseting = g.offset(reg.corner);
1817 size_t offsetinthis = 0;
1818 *this = DimsGraphic{reg.area}; // create room
1819 for (typename HEIGHTRESOL::type y = 0; y < h ; ++y)
1820 {
1821 LinearGraphic::mergeUnsafe(offsetinthis, g, offseting, w);
1822 offsetinthis += dims.width;
1823 offseting += g.dims.width;
1824 }
1825 }
1826 else
1827 {
1828 // form a reference to G
1829 this->LinearGraphic::operator=(
1830 LinearGraphic{g,g.offset(reg.corner),w,
1831 static_cast<size_t>(g.dims.width - w),
1832 reg.area.height});
1833 dims = reg.area;
1834 }
1835}
1836
1837template <typename HEIGHTRESOL>
1839{
1840 if ((pos.x >= dims.width) || (pos.y >= dims.height))
1841 RUNTIMEEXCEP(std::string{"Coordinates "} + pos.to_string() +
1842 " out of range in DimsGraphic " + to_string());
1843 return(static_cast<size_t>(pos.y) *
1844 static_cast<size_t>(dims.width) +
1845 static_cast<size_t>(pos.x));
1846}
1847
1848template <typename HEIGHTRESOL>
1851{
1852 if (offset >= s_) RUNTIMEEXCEP("Offset out of range in DimsGraphic");
1853 return(CursorType{static_cast<typename HEIGHTRESOL::coord_typeT::type>
1854 (offset % dims.width),
1855 static_cast<CharCoord>(offset / dims.width)});
1856}
1857
1858template <typename HEIGHTRESOL>
1860 const CursorType & pos,
1861 GraphOp mode)
1862{
1863 if (oneByte())
1864 RUNTIMEEXCEP("Cannot merge nothing on a one-byte DimsGraphic");
1865
1866 if ((oth.dims.width == 0) || (oth.dims.height == 0)) return;
1867
1868 // pointer to the byte of the first byte in this graphic
1869 size_t thisoffset = static_cast<size_t>(pos.y) *
1870 static_cast<size_t>(dims.width) +
1871 static_cast<size_t>(pos.x);
1872
1873 const CharDist firstinvisiblebinthis =
1874 std::min(oth.dims.width, static_cast<CharDist>(dims.width - pos.x));
1875 const typename HEIGHTRESOL::type firstinvisibleyg =
1876 std::min(oth.dims.height, static_cast<typename HEIGHTRESOL::type>(
1877 dims.height - pos.y));
1878
1879 for (typename HEIGHTRESOL::coord_typeT::type yg = 0;
1880 yg < firstinvisibleyg; ++yg)
1881 {
1882 LinearGraphic::mergeUnsafe(thisoffset, // destination
1883 oth, oth.offset({0,yg}), // origin
1884 firstinvisiblebinthis, // howmany
1885 mode);
1886 thisoffset += static_cast<size_t>(dims.width);
1887 }
1888}
1889
1890template <typename HEIGHTRESOL>
1892{
1893 return(std::string{"DimsGraphic<"} +
1894 AreaType::HeightType::name + ">{ width: " +
1895 std::to_string((unsigned)dims.width) + ", height: " +
1896 std::to_string((unsigned)dims.height) + "; " +
1897 LinearGraphic::to_string() + " }");
1898}
1899
1900
1901
1902/*============================================================================
1903
1904 GLOBAL ASSERTS
1905
1906==============================================================================*/
1907
1908
1909static_assert(std::is_integral<PixelCoord>::value &&
1910 std::is_unsigned<PixelCoord>::value,
1911 "PixelCoord type must be integral and unsigned");
1912static_assert(std::is_integral<CharCoord>::value &&
1913 std::is_unsigned<CharCoord>::value,
1914 "CharCoord type must be integral and unsigned");
1915static_assert(std::is_integral<PixelDist>::value &&
1916 std::is_unsigned<PixelDist>::value,
1917 "PixelDist type must be integral and unsigned");
1918static_assert(std::is_integral<CharDist>::value &&
1919 std::is_unsigned<CharDist>::value,
1920 "CharDist type must be integral and unsigned");
1921static_assert(std::is_integral<IntDist>::value &&
1922 std::is_signed<IntDist>::value,
1923 "IntDist type must be integral and signed");
1924
1925
1926} // end namespace zxeco
1927
1928#endif
1929 // ZXGraphics
1931
uint32_t Size
Size of a palette.
Definition: ColorImages.h:151
Size numColors(void) const noexcept
Return the number of colors in the palette.
Definition: ColorImages.h:173
Size Index
Index of a color in a palette.
Definition: ColorImages.h:154
RasterCursor< 1, 1 > subCursor(void) const
Return a cursor limited to the cell where this cursor is.
Definition: ColorImages.h:298
An image that stores pixel colors contiguously as palette indexes.
Definition: ColorImages.h:530
A RGB color with 8 bits per component.
Definition: ColorImages.h:47
A palette defining a number of RGB colors.
Definition: ColorImages.h:147
A cursor to access RasterImage pixels bi-linearly with certain tesselation.
Definition: ColorImages.h:227
A 2D matrix of certain type that has contiguous storage.
Definition: ColorImages.h:434
Collect diverse traits for the fixed integer type T.
Definition: CppAddons.h:124
An interval, typically numeric, either closed, opened or semi-closed.
Definition: CppAddons.h:470
#define RUNTIMEEXCEP(txt)
Raise a runtime exception with the given std::string TXT + additional info.
Definition: CppAddons.h:93
Interface with the functionality that a desktop must provide.
static constexpr RGBPalette::Size NUMLINEARCOLORS
Number of linear colors. Black is counted twice, being equal w & w/o br.
Definition: ZXColors.h:201
DimsGraphic(const AreaType &a, uint8_t b)
Construct a graphic of the given dimensions filled with one byte (B).
Definition: ZXGraphics.h:1031
static const Rect & theEmpty(void) noexcept
Return a reference to an inmutable empty rectangle of this type.
Definition: ZXGraphics.h:652
HRES HeightType
Type used for the height dimension.
Definition: ZXGraphics.h:363
cursor_type bottomRight(void) const noexcept
< Return the coordinates of the bottom-right extreme within the rectangle
Definition: ZXGraphics.h:668
LinearGraphic(uint8_t *bs, size_t s)
Construct a graphic that is held externally (NO OWNERSHIP to this).
Rect(const cursor_type &c=cursor_type{0, 0}, const area_type &a=area_type{0, 0})
Default constructor: empty rectangle.
Definition: ZXGraphics.h:658
HRES HeightType
Type used for the height dimension.
Definition: ZXGraphics.h:508
static constexpr uint8_t doGraphOp(uint8_t b0, uint8_t b1) noexcept
Return the result of doing operation OP on byte B0 with byte B1.
Area & operator*=(const Area &oth)
Intersect OTH to THIS and return THIS.
Definition: ZXGraphics.h:575
area_type area
Width and height.
Definition: ZXGraphics.h:650
std::string to_string(void) const
Return a text with the info of the graphic.
Definition: ZXGraphics.h:1355
DimsGraphic & operator=(DimsGraphic &&oth)
Move assignment.
Definition: ZXGraphics.h:1056
PixRect getPixRect(const CharRect &cc)
Convert a char rect to a pix rect representing the same region on screen.
Definition: ZXGraphics.h:748
CharArea chararea
Char resolution.
Definition: ZXGraphics.h:772
Cursor< typename WRES::coord_typeT, typename HRES::coord_typeT > CursorType
Cursor.
Definition: ZXGraphics.h:510
bool empty(void) const noexcept
Return TRUE if the area is empty.
Definition: ZXGraphics.h:535
LinearGraphic(size_t s)
Construct an empty graphic of the given size, yet to be filled.
void merge(const DimsGraphic &oth, const CursorType &pos, GraphOp mode=GraphOp::COPY)
Merge OTH at the given coordinates of this object with the given mode.
Definition: ZXGraphics.h:1859
constexpr CharCoord kMaxCharCoord
Maximum value of a char coordinate.
Definition: ZXGraphics.h:108
type value
To hold values of that type.
Definition: ZXGraphics.h:340
CharDist type
Numerical type corresponding to this class.
Definition: ZXGraphics.h:289
bool oneByte(void) const noexcept
Return TRUE if the graphic content is compressed into one byte.
Definition: ZXGraphics.h:913
Bitmap(uint8_t ascii, uint8_t *chartable=nullptr)
Construct a bitmap for a ZX ascii char (including block-graphic ones).
constexpr CharDist SCREENCOLS
Number of columns in the screen of the original ZX.
Definition: ZXGraphics.h:235
bool empty(void) const noexcept
Return TRUE if the rectangle area is empty.
Definition: ZXGraphics.h:662
PixCursor getPixCursor(const CharCursor &cc)
Convert a char cursor to a pix cursor placed at the top-left of the former.
Definition: ZXGraphics.h:481
type value
To hold values of that type.
Definition: ZXGraphics.h:283
static const Cursor & theZero(void) noexcept
< Return a reference to an inmutable zero cursorof this type.
Definition: ZXGraphics.h:368
constexpr size_t DISPLAYLEN
Length in memory (bytes) of the original complete zx screen.
Definition: ZXGraphics.h:207
void swapPaperInk(void)
< Reuse all constructor from Gr<CharDistT>.
uint8_t getByte(size_t offset) const
Get the byte at the given offset, throwing if it is out of range.
static constexpr const char * name
Name of numeric type.
Definition: ZXGraphics.h:326
Area< CharDistT, CharDistT > CharArea
Shortcut for this kind of area.
Definition: ZXGraphics.h:605
CursorType coords(size_t offset) const
Get the coordinates of the given offset, if it is valid, or throws.
Definition: ZXGraphics.h:1850
WRES WidthType
Type used for the width dimension.
Definition: ZXGraphics.h:362
type value
To hold values of that type.
Definition: ZXGraphics.h:318
PNGConversionMode mode
Mode for conversion.
Definition: ZXGraphics.h:1276
constexpr BorderDist TOPBORDERH
Height in pixels of the original zx visible border in its top section.
Definition: ZXGraphics.h:190
constexpr PixelDist SCREENH
Height in pixels of the original zx screen.
Definition: ZXGraphics.h:188
void newRow(void) noexcept
Go down one row resetting x (y <- y + 1 & x <- 0).
Definition: ZXGraphics.h:386
PixelDist type
Numerical type corresponding to this class.
Definition: ZXGraphics.h:301
IntDist yDiff(const Cursor &oth) const noexcept
< Return the signed distance in Y from OTH to THIS.
Definition: ZXGraphics.h:412
DimsGraphic(DimsGraphic &&oth)
Move constructor.
Definition: ZXGraphics.h:1052
constexpr BorderCoord kMaxBorderCoord
Maximum value of a border pixel coordinate.
Definition: ZXGraphics.h:123
void incRow(void) noexcept
Go down one row without resetting x.
Definition: ZXGraphics.h:392
bool containedInto(const Area &oth) const noexcept
< Return TRUE if this area can be contained into OTH or if they are equal
Definition: ZXGraphics.h:542
bool operator==(const Area &oth) const noexcept
< Equality.
Definition: ZXGraphics.h:579
size_t offset(const CursorType &pos) const
Get the offset corresponding to the given coordinates in the graphic.
Definition: ZXGraphics.h:1838
type value
To hold values of that type.
Definition: ZXGraphics.h:273
HEIGHTRESOL::type scrollUp(typename HEIGHTRESOL::type howmany, typename HEIGHTRESOL::type upperrow, uint8_t fillb)
Scroll HOWMANY rows of the graphic up, beginning at y-coord UPPERROW.
Definition: ZXGraphics.h:1104
type value
To hold values of that type.
Definition: ZXGraphics.h:328
void addDiff(IntDist xdiff, IntDist ydiff) noexcept
< Add the given signed distances to both coordinates.
Definition: ZXGraphics.h:416
size_t area(void) const noexcept
< Return the number of cells in the area.
Definition: ZXGraphics.h:538
Area & operator-=(const Area &oth)
Substract OTH from THIS and return THIS. Throw if error.
Definition: ZXGraphics.h:565
Cursor & operator+=(const Cursor &oth)
Make the sum and return the result.
Definition: ZXGraphics.h:437
static constexpr const char * name
Name of numeric type.
Definition: ZXGraphics.h:305
WidthType::type width
width of the area.
Definition: ZXGraphics.h:512
constexpr PixelDist SCREENW
Width in pixels of the original zx screen.
Definition: ZXGraphics.h:186
CharPixArea getCharPixArea(const CharArea &cc)
Convert a char area to a char-pix area covering the same region on screen.
Definition: ZXGraphics.h:627
constexpr CharDist SCREENROWS
Number of rows in the screen of the original ZX.
Definition: ZXGraphics.h:232
bool applyConstrainedDiffs(IntDist &xdiff, IntDist &ydiff, const Rect &oth) noexcept
Apply the given increments to the corner of THIS, keeping it within OTH.
Definition: ZXGraphics.h:1564
uint8_t * getAllBytes(void)
Return a pointer to the data or throw if it is onebyte or external.
bool rightBelow(const Cursor &oth) const noexcept
< Return TRUE if THIS is placed to the right and below of OTH.
Definition: ZXGraphics.h:403
void mergeUnsafe(size_t destoffset, const LinearGraphic &oth, size_t origoffset, size_t howmany, GraphOp op=GraphOp::COPY)
Merge HOWMANY bytes from OTH (at ORIGOFFSET) into this (at DESTOFFSET).
static constexpr const char * name
Name of numeric type.
Definition: ZXGraphics.h:316
constexpr BorderDist BOTTOMBORDERH
Height in pixels of the original zx visible border in its bottom section.
Definition: ZXGraphics.h:193
constexpr PixelDist kMaxPixelDist
Maximum value of a pixel distance.
Definition: ZXGraphics.h:111
bool operator!=(const Cursor &oth) const noexcept
< Unequality.
Definition: ZXGraphics.h:427
void merge(const DoubleGraphic &oth, const CharCursor &pos, LinearGraphic::GraphOp mode=LinearGraphic::GraphOp::COPY)
Merge both bitmap and attrmap of OTH at the given coordinates in MODE.
Definition: ZXGraphics.h:1346
Area operator*(const Area &oth) const
< Intersect OTH dimensions to THIS dims and return the result.
Definition: ZXGraphics.h:570
std::string to_string(void) const
Return a text with the info of the graphic.
type value
To hold values of that type.
Definition: ZXGraphics.h:295
constexpr PixelCoord pixelOfCharX(CharCoord cc) noexcept
Conversion from an x-CharCoord to PixelCoord.
Definition: ZXGraphics.h:167
void setByteUnsafe(size_t offset, uint8_t b) noexcept
Change the byte at the given offset without checking anything.
DimsGraphic(DimsGraphic &g, const RectType &region, bool copy=true)
Construct a graphic that refers to a region within another one.
Definition: ZXGraphics.h:1786
struct zxeco::DoubleGraphic::PNGConversionParms::@2 tonearestplain
Parms for ToNearestPlain mode.
Area(typename WidthType::type w, typename HeightType::type h)
Default constructor, from the numerical dist types.
Definition: ZXGraphics.h:520
std::string to_string(void) const
Return a text with the info of the graphic.
Definition: ZXGraphics.h:1237
constexpr PixelCoord firstPixelInCharX(PixelCoord pc) noexcept
Get the PixelCoord of 1st pixel in the character of this x-PixelCoord.
Definition: ZXGraphics.h:145
PNGConversionMode
Modes of conversion of PNG images into DoubleGraphic.
Definition: ZXGraphics.h:1256
constexpr BorderDist RIGHTBORDERW
Height in pixels of the original zx visible border in its right section.
Definition: ZXGraphics.h:197
PNGConversionSubmode
Submode of conversion of PNG images into DoubleGraphic.
Definition: ZXGraphics.h:1264
LinearGraphic(void)
Default constructor: empty graphic.
PixArea pixarea
Pixel resolution.
Definition: ZXGraphics.h:773
AreaType dims
Dimensions of the graphic.
Definition: ZXGraphics.h:1019
constexpr PixelCoord pixelOfCharY(CharCoord cc) noexcept
Conversion from a y-CharCoord to PixelCoord.
Definition: ZXGraphics.h:173
constexpr PixelCoord kMaxPixelCoord
Maximum value of a pixel coordinate.
Definition: ZXGraphics.h:105
constexpr BorderDist kMaxBorderDist
Maximum value of a border pixel distance.
Definition: ZXGraphics.h:126
bool operator==(const Rect &oth) const noexcept
< Equality.
Definition: ZXGraphics.h:712
DoubleGraphic(const CharArea &dims)
Constructor for a given size in characters.
Definition: ZXGraphics.h:1301
void setByte(const CursorType &pos, uint8_t b)
< Unhide the linear setByte() method hidden by the new setByte().
Definition: ZXGraphics.h:1079
CharPixCursor getCharPixCursor(const CharCursor &cc)
Convert a char cursor to a char-pix cursor placed at the top of the former.
Definition: ZXGraphics.h:489
struct zxeco::DoubleGraphic::PNGConversionParms::@3 dither
Parms for Dither and its submodes.
GraphOp
Possible operations on Graphics.
Definition: ZXGraphics.h:841
Area operator-(const Area &oth) const
< Substract OTH dimensions from THIS dims and return the result, or throw
Definition: ZXGraphics.h:556
DimsGraphic(uint8_t *bs, const AreaType &a)
Construct a graphic that is held externally (NO OWNERSHIP to this).
Definition: ZXGraphics.h:1036
bool contains(const cursor_type &cur) const noexcept
Return TRUE if CUR is inside the rectangle.
Definition: ZXGraphics.h:1557
int compare(const LinearGraphic &oth, bool withinv=false) const noexcept
Compare this graphic to OTH and return 1 if both are equal.
constexpr CharDist kMaxCharDist
Maximum value of a char distance.
Definition: ZXGraphics.h:114
void setAllBytes(uint8_t b) noexcept
Set all bytes of the graphic to the given value.
CharPixRect getCharPixRect(const CharRect &cc)
Convert a char rect to a char-pix rect representing the same region.
Definition: ZXGraphics.h:756
PixRect pixrect
Pixel resolution.
Definition: ZXGraphics.h:803
uint8_t NumDithLevels
Type for storing number of dithering levels.
Definition: ZXGraphics.h:1271
static constexpr const char * name
Name of numeric type.
Definition: ZXGraphics.h:293
void savePNG(DesktopInterface &desktop, const std::string &pngfile)
Save the double graphic into a PNG file.
constexpr IntDist kMinIntDist
Minimum value of an int distance.
Definition: ZXGraphics.h:117
Rect subRect(const cursor_type &reltopleft) const
< Return the absolute sub-rectangle that starts at RELTOPLEFT within this
Definition: ZXGraphics.h:691
void newCol(void) noexcept
Go right one column (x <- x + 1).
Definition: ZXGraphics.h:389
uint16_t PixelDist
A distance measured in screen pixels.
Definition: ZXGraphics.h:96
bool graphicDimensionsTooLarge(unsigned sx, unsigned sy) noexcept
< Return TRUE if SX,SY are too large to fit in WITHRESOL,HEIGHTRESOL.
Definition: ZXGraphics.h:1137
type value
To hold values of that type.
Definition: ZXGraphics.h:307
void merge(size_t destoffset, const LinearGraphic &oth, size_t origoffset, size_t howmany, GraphOp op=GraphOp::COPY)
Merge HOWMANY bytes from OTH (at ORIGOFFSET) into this (at DESTOFFSET).
uint16_t CharCoord
Represent both x and y screen char coordinates.
Definition: ZXGraphics.h:94
constexpr CharDist pixelDistToCharDist(PixelDist cc, bool toceil=true) noexcept
Conversion from PixelDist to CharDist.
Definition: ZXGraphics.h:224
constexpr IntDist kMaxIntDist
Maximum value of an int distance.
Definition: ZXGraphics.h:120
size_t similarity(const LinearGraphic &oth) const noexcept
Return a measure of the bitmap similarity (bit by bit) between both.
BorderCoord type
Numerical type corresponding to this class.
Definition: ZXGraphics.h:324
HeightType::type height
height of the area.
Definition: ZXGraphics.h:513
IntDist type
Numerical type corresponding to this class.
Definition: ZXGraphics.h:314
std::string to_string(bool withtype=true) const
< Return a string with the textual information of the rectangle.
Definition: ZXGraphics.h:720
constexpr PixelDist charDistToPixelDist(CharDist pc) noexcept
Conversion from CharDist to PixelDist.
Definition: ZXGraphics.h:215
uint8_t getByte(const CursorType &pos) const
< Unhide the linear getByte() method hidden by the new getByte().
Definition: ZXGraphics.h:1072
Rect intersect(const Rect &oth) const noexcept
Return the rectangle resulting from the intersection of this and OTH.
Definition: ZXGraphics.h:1593
uint16_t PixelCoord
Represent both x and y screen pix coordinates.
Definition: ZXGraphics.h:93
constexpr PixelCoord firstPixelInCharY(PixelCoord pc) noexcept
Get the PixelCoord of 1st pixel in the character of this y-PixelCoord.
Definition: ZXGraphics.h:151
CharRect charrect
Char resolution.
Definition: ZXGraphics.h:802
bool operator==(const Cursor &oth) const noexcept
< Return TRUE if both cursors are placed at the same place.
Definition: ZXGraphics.h:423
WRES WidthType
Type used for the width dimension.
Definition: ZXGraphics.h:507
DimsGraphic(const AreaType &a)
Construct an undefined graphic of the given dimensions, to be filled.
Definition: ZXGraphics.h:1027
void merge(const Bitmap &oth, const PixCursor &pos, GraphOp mode=GraphOp::COPY)
< Unhide the base merge() method hidden by the new merge().
cursor_type corner
Top-left corner.
Definition: ZXGraphics.h:649
Cursor operator-(const Cursor &oth) const
< Return the cursor THIS relative to OTH, or throw if result is negative.
Definition: ZXGraphics.h:440
static const Area & theEmpty(void) noexcept
Return a reference to an inmutable empty area of this type.
Definition: ZXGraphics.h:515
Cursor(typename WidthType::type xc, typename HeightType::type yc)
Constructor, from the numerical coord types.
Definition: ZXGraphics.h:377
Area operator+(const Area &oth) const noexcept
< Add width and height of OTH to THIS.
Definition: ZXGraphics.h:546
int16_t IntDist
Positive and negative distances on screen.
Definition: ZXGraphics.h:99
PNGConversionSubmode submode
Submode.
Definition: ZXGraphics.h:1277
constexpr size_t BITMAPLEN
Length in memory (bytes) of the original zx screen bitmap.
Definition: ZXGraphics.h:203
size_t size(void) const noexcept
Size in memory, in bytes.
Definition: ZXGraphics.h:907
Cursor operator+(const Cursor &oth) const
< Return the sum of both cursors.
Definition: ZXGraphics.h:431
Bitmap(DesktopInterface &desktop, const std::string &pngfile)
< Reuse all constructor from Gr<PixelDistT>.
PixArea getPixArea(const CharArea &cc)
Convert a char area to a pix area covering the same region on screen.
Definition: ZXGraphics.h:618
LinearGraphic(size_t s, uint8_t b)
Construct a graphic of the given size filled with 1 byte (B).
Rect compose(const Rect &reloth) const
< Return the RELOTH region of THIS as a rectangle.
Definition: ZXGraphics.h:681
CharCoord type
Numerical type corresponding to this class.
Definition: ZXGraphics.h:269
bool operator!=(const Area &oth) const noexcept
< Unequality.
Definition: ZXGraphics.h:583
Cursor & operator-=(const Cursor &oth)
Make the substraction and return the result.
Definition: ZXGraphics.h:448
LinearGraphic(LinearGraphic &oth, size_t firstoff, size_t chunksize, size_t gap, size_t numchunks)
Construct a graphic referring to part of another one (no ownership).
bool operator!=(const Rect &oth) const noexcept
< Unequality.
Definition: ZXGraphics.h:716
void setByte(size_t offset, uint8_t b)
Change the byte at the given offset inside the data.
PixelCoord type
Numerical type corresponding to this class.
Definition: ZXGraphics.h:279
uint8_t getByteUnsafe(size_t offset) const noexcept
Get the byte at the given offset without checking out of range.
static Cursor max(const Cursor &c0, const Cursor &c1) noexcept
< Return a copy of the one of C0, C1 that is more to the right and below.
Definition: ZXGraphics.h:372
bool zero(void) const noexcept
Return TRUE if the cursor is placed at (0,0). *‍/.
Definition: ZXGraphics.h:395
Rect align_area(const area_type &areaneeded, char horalign, char vertalign) const
Return the portion of this rectangle that contains AREANEEDED aligned.
Definition: ZXGraphics.h:1628
constexpr CharDist SCREENCHARROWS
Number of char rows in the screen.
Definition: ZXGraphics.h:201
NumDithLevels numlevels
Number of dithering levels.
Definition: ZXGraphics.h:1281
std::string to_string(bool withtype=true) const
< Return a string with the textual information of the area.
Definition: ZXGraphics.h:587
bool external(void) const noexcept
Whether the object refers to part of another linear graphic.
Definition: ZXGraphics.h:900
static constexpr const char * name
Name of numeric type.
Definition: ZXGraphics.h:271
std::string to_string(bool withtype=true) const
< Return a string with the textual information of the area.
Definition: ZXGraphics.h:451
constexpr CharCoord charOfPixelX(PixelCoord pc) noexcept
Conversion from an x-PixelCoord to CharCoord.
Definition: ZXGraphics.h:134
BorderDist type
Numerical type corresponding to this class.
Definition: ZXGraphics.h:334
bool before(const Cursor &oth) const noexcept
< Return TRUE if THIS is placed before OTH in the plane (linearly).
Definition: ZXGraphics.h:398
bool owner(void) const noexcept
Whether the object owns the graphical data.
Definition: ZXGraphics.h:903
WidthType::type x
Coordinate in width (horizontally).
Definition: ZXGraphics.h:365
int16_t BorderCoord
Represent both x and y pix coords in border.
Definition: ZXGraphics.h:101
constexpr CharDist SCREENCHARCOLS
Number of char columns in the screen.
Definition: ZXGraphics.h:199
std::string to_string(void) const
Return a text with the info of the graphic.
Definition: ZXGraphics.h:1207
static constexpr const char * name
Name of numeric type.
Definition: ZXGraphics.h:281
static constexpr const char * name
Name of numeric type.
Definition: ZXGraphics.h:338
IntDist xDiff(const Cursor &oth) const noexcept
< Return the signed distance in X from OTH to THIS.
Definition: ZXGraphics.h:408
constexpr size_t ATTRMAPLEN
Length in memory (bytes) of the original zx screen attrmap.
Definition: ZXGraphics.h:205
Area & operator+=(const Area &oth) noexcept
< Add to THIS the width and height of OTH.
Definition: ZXGraphics.h:552
DimsGraphic(void)
Default constructor: empty graphic.
Definition: ZXGraphics.h:1024
HeightType::type y
Coordinates in height (vertically).
Definition: ZXGraphics.h:366
uint16_t CharDist
A distance meadured in screen chars.
Definition: ZXGraphics.h:97
constexpr CharCoord charOfPixelY(PixelCoord pc) noexcept
Conversion from an y-PixelCoord to CharCoord.
Definition: ZXGraphics.h:139
constexpr unsigned char bitOfPixelX(PixelCoord pc) noexcept
Get the bit position of the pixel of this x-PixelCoord.
Definition: ZXGraphics.h:158
constexpr BorderDist LEFTBORDERW
Height in pixels of the original zx visible border in its left section.
Definition: ZXGraphics.h:195
std::string to_string(void) const
Return a text with the info of the graphic.
Definition: ZXGraphics.h:1891
uint16_t BorderDist
A distance measured in pixels in the border.
Definition: ZXGraphics.h:102
@ OR
OR the graphic and the screen content.
@ INV
like COPY but with the graphic bits inverted first
@ AND
AND the graphic and the screen content.
@ INVAND
like AND but first inverts the graphic bits
@ INVXOR
like XOR but with the graphic bits inverted first
@ INVOR
like OR but first invert the graphic bits
@ XOR
XOR the graphic and the screen content.
@ COPY
put the graphic on the screen (substitution)
An area on the screen that uses the given distance resolutions.
Definition: ZXGraphics.h:504
A graphic that contains an attrmap, i.e., it has char resolution in height.
Definition: ZXGraphics.h:1221
A graphic that contains a bitmap, i.e., it has pixel resolution in height.
Definition: ZXGraphics.h:1151
A cursor on screen that uses the given coordinates resolution.
Definition: ZXGraphics.h:359
A graphic that has certain 2D dimensions and coordinates.
Definition: ZXGraphics.h:1009
An area with both char and pixel resolutions, possibly synchronized.
Definition: ZXGraphics.h:769
A bitmap plus an attrmap, possibly synchronized.
Definition: ZXGraphics.h:1250
A rectangle with both char and pixel resolutions, possibly synchronized.
Definition: ZXGraphics.h:799
A rectangular graphic block.
Definition: ZXGraphics.h:834
A class that makes BorderCoord a different, distinguishable type from others.
Definition: ZXGraphics.h:323
A class that makes BorderDist a different, distinguishable type from others.
Definition: ZXGraphics.h:333
A class that makes CharCoord a different, distinguishable type from others.
Definition: ZXGraphics.h:268
A class that makes CharDist a different, distinguishable type from others.
Definition: ZXGraphics.h:288
Base class for all coordinate trait classes.
Definition: ZXGraphics.h:255
Base class for all distance trait classes.
Definition: ZXGraphics.h:263
Parameters for the conversion of PNG images into DoubleGraphic.
Definition: ZXGraphics.h:1275
A class that makes IntDist a different, distinguishable type from others.
Definition: ZXGraphics.h:313
A class that makes PixelCoord a different, distinguishable type from others.
Definition: ZXGraphics.h:278
A class that makes PixelDist a different, distinguishable type from others.
Definition: ZXGraphics.h:300
A rectangle placed on the screen that uses the given resolutions.
Definition: ZXGraphics.h:644
The main namespace of the library, that spans across all the zx modules.
Definition: ZXChars.h:31