1 // This module implements the QsciPrinter class.
2 //
3 // Copyright (c) 2021 Riverbank Computing Limited <info@riverbankcomputing.com>
4 //
5 // This file is part of QScintilla.
6 //
7 // This file may be used under the terms of the GNU General Public License
8 // version 3.0 as published by the Free Software Foundation and appearing in
9 // the file LICENSE included in the packaging of this file. Please review the
10 // following information to ensure the GNU General Public License version 3.0
11 // requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 //
13 // If you do not wish to use this file under the terms of the GPL version 3.0
14 // then you may purchase a commercial license. For more information contact
15 // info@riverbankcomputing.com.
16 //
17 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19
20
21 #include "Qsci/qsciprinter.h"
22
23 #if !defined(QT_NO_PRINTER)
24
25 #include <QPrinter>
26 #include <QPainter>
27 #include <QStack>
28
29 #include "Qsci/qsciscintillabase.h"
30
31
32 // The ctor.
QsciPrinter(QPrinter::PrinterMode mode)33 QsciPrinter::QsciPrinter(QPrinter::PrinterMode mode)
34 : QPrinter(mode), mag(0), wrap(QsciScintilla::WrapWord)
35 {
36 }
37
38
39 // The dtor.
~QsciPrinter()40 QsciPrinter::~QsciPrinter()
41 {
42 }
43
44
45 // Format the page before the document text is drawn.
formatPage(QPainter &,bool,QRect &,int)46 void QsciPrinter::formatPage(QPainter &, bool, QRect &, int)
47 {
48 }
49
50
51 // Print a range of lines to a printer using a supplied QPainter.
printRange(QsciScintillaBase * qsb,QPainter & painter,int from,int to)52 int QsciPrinter::printRange(QsciScintillaBase *qsb, QPainter &painter,
53 int from, int to)
54 {
55 // Sanity check.
56 if (!qsb)
57 return false;
58
59 // Setup the printing area.
60 QRect def_area;
61
62 def_area.setX(0);
63 def_area.setY(0);
64 def_area.setWidth(width());
65 def_area.setHeight(height());
66
67 // Get the page range.
68 int pgFrom, pgTo;
69
70 pgFrom = fromPage();
71 pgTo = toPage();
72
73 // Find the position range.
74 long startPos, endPos;
75
76 endPos = qsb->SendScintilla(QsciScintillaBase::SCI_GETLENGTH);
77
78 startPos = (from > 0 ? qsb -> SendScintilla(QsciScintillaBase::SCI_POSITIONFROMLINE,from) : 0);
79
80 if (to >= 0)
81 {
82 long toPos = qsb -> SendScintilla(QsciScintillaBase::SCI_POSITIONFROMLINE,to + 1);
83
84 if (endPos > toPos)
85 endPos = toPos;
86 }
87
88 if (startPos >= endPos)
89 return false;
90
91 bool reverse = (pageOrder() == LastPageFirst);
92 bool needNewPage = false;
93 int nr_copies = supportsMultipleCopies() ? 1 : copyCount();
94
95 qsb -> SendScintilla(QsciScintillaBase::SCI_SETPRINTMAGNIFICATION,mag);
96 qsb -> SendScintilla(QsciScintillaBase::SCI_SETPRINTWRAPMODE,wrap);
97
98 for (int i = 1; i <= nr_copies; ++i)
99 {
100 // If we are printing in reverse page order then remember the start
101 // position of each page.
102 QStack<long> pageStarts;
103
104 int currPage = 1;
105 long pos = startPos;
106
107 while (pos < endPos)
108 {
109 // See if we have finished the requested page range.
110 if (pgTo > 0 && pgTo < currPage)
111 break;
112
113 // See if we are going to render this page, or just see how much
114 // would fit onto it.
115 bool render = false;
116
117 if (pgFrom == 0 || pgFrom <= currPage)
118 {
119 if (reverse)
120 pageStarts.push(pos);
121 else
122 {
123 render = true;
124
125 if (needNewPage)
126 {
127 if (!newPage())
128 return false;
129 }
130 else
131 needNewPage = true;
132 }
133 }
134
135 QRect area = def_area;
136
137 formatPage(painter,render,area,currPage);
138 pos = qsb -> SendScintilla(QsciScintillaBase::SCI_FORMATRANGE,render,&painter,area,pos,endPos);
139
140 ++currPage;
141 }
142
143 // All done if we are printing in normal page order.
144 if (!reverse)
145 continue;
146
147 // Now go through each page on the stack and really print it.
148 while (!pageStarts.isEmpty())
149 {
150 --currPage;
151
152 long ePos = pos;
153 pos = pageStarts.pop();
154
155 if (needNewPage)
156 {
157 if (!newPage())
158 return false;
159 }
160 else
161 needNewPage = true;
162
163 QRect area = def_area;
164
165 formatPage(painter,true,area,currPage);
166 qsb->SendScintilla(QsciScintillaBase::SCI_FORMATRANGE,true,&painter,area,pos,ePos);
167 }
168 }
169
170 return true;
171 }
172
173
174 // Print a range of lines to a printer using a default QPainter.
printRange(QsciScintillaBase * qsb,int from,int to)175 int QsciPrinter::printRange(QsciScintillaBase *qsb, int from, int to)
176 {
177 QPainter painter(this);
178
179 return printRange(qsb, painter, from, to);
180 }
181
182
183 // Set the print magnification in points.
setMagnification(int magnification)184 void QsciPrinter::setMagnification(int magnification)
185 {
186 mag = magnification;
187 }
188
189
190 // Set the line wrap mode.
setWrapMode(QsciScintilla::WrapMode wmode)191 void QsciPrinter::setWrapMode(QsciScintilla::WrapMode wmode)
192 {
193 wrap = wmode;
194 }
195
196 #endif
197