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