1 #include "nup.h"
2 #include <stdio.h>
3 #include <assert.h>
4 #include <string.h>
5 #include <utility>
6
dump() const7 void NupParameters::dump() const // {{{
8 {
9 fprintf(stderr,"NupX: %d, NupY: %d\n"
10 "width: %f, height: %f\n",
11 nupX,nupY,
12 width,height);
13
14 int opos=-1,fpos=-1,spos=-1;
15 if (xstart==Position::LEFT) { // or Bottom
16 fpos=0;
17 } else if (xstart==Position::RIGHT) { // or Top
18 fpos=1;
19 }
20 if (ystart==Position::LEFT) { // or Bottom
21 spos=0;
22 } else if (ystart==Position::RIGHT) { // or Top
23 spos=1;
24 }
25 if (first==Axis::X) {
26 fprintf(stderr,"First Axis: X\n");
27 opos=0;
28 } else if (first==Axis::Y) {
29 fprintf(stderr,"First Axis: Y\n");
30 opos=2;
31 std::swap(fpos,spos);
32 }
33
34 if ( (opos==-1)||(fpos==-1)||(spos==-1) ) {
35 fprintf(stderr,"Bad Spec: %d; start: %d, %d\n\n",
36 first,xstart,ystart);
37 } else {
38 static const char *order[4]={"lr","rl","bt","tb"};
39 fprintf(stderr,"Order: %s%s\n",
40 order[opos+fpos],order[(opos+2)%4+spos]);
41 }
42
43 fputs("Alignment: ",stderr);
44 Position_dump(xalign,Axis::X);
45 fputs("/",stderr);
46 Position_dump(yalign,Axis::Y);
47 fputs("\n",stderr);
48 }
49 // }}}
50
possible(int nup)51 bool NupParameters::possible(int nup) // {{{
52 {
53 // 1 2 3 4 6 8 9 10 12 15 16
54 return (nup>=1)&&(nup<=16)&&
55 ( (nup!=5)&&(nup!=7)&&(nup!=11)&&(nup!=13)&&(nup!=14) );
56 }
57 // }}}
58
preset(int nup,NupParameters & ret)59 void NupParameters::preset(int nup,NupParameters &ret) // {{{
60 {
61 switch (nup) {
62 case 1:
63 ret.nupX=1;
64 ret.nupY=1;
65 break;
66 case 2:
67 ret.nupX=2;
68 ret.nupY=1;
69 ret.landscape=true;
70 break;
71 case 3:
72 ret.nupX=3;
73 ret.nupY=1;
74 ret.landscape=true;
75 break;
76 case 4:
77 ret.nupX=2;
78 ret.nupY=2;
79 break;
80 case 6:
81 ret.nupX=3;
82 ret.nupY=2;
83 ret.landscape=true;
84 break;
85 case 8:
86 ret.nupX=4;
87 ret.nupY=2;
88 ret.landscape=true;
89 break;
90 case 9:
91 ret.nupX=3;
92 ret.nupY=3;
93 break;
94 case 10:
95 ret.nupX=5;
96 ret.nupY=2;
97 ret.landscape=true;
98 break;
99 case 12:
100 ret.nupX=3;
101 ret.nupY=4;
102 break;
103 case 15:
104 ret.nupX=5;
105 ret.nupY=3;
106 ret.landscape=true;
107 break;
108 case 16:
109 ret.nupX=4;
110 ret.nupY=4;
111 break;
112 }
113 }
114 // }}}
115
116
NupState(const NupParameters & param)117 NupState::NupState(const NupParameters ¶m) // {{{
118 : param(param),
119 in_pages(0),out_pages(0),
120 nup(param.nupX*param.nupY),
121 subpage(nup)
122 {
123 assert( (param.nupX>0)&&(param.nupY>0) );
124 }
125 // }}}
126
reset()127 void NupState::reset() // {{{
128 {
129 in_pages=0;
130 out_pages=0;
131 // nup=param.nupX*param.nupY;
132 subpage=nup;
133 }
134 // }}}
135
dump() const136 void NupPageEdit::dump() const // {{{
137 {
138 fprintf(stderr,"xpos: %f, ypos: %f, scale: %f\n",
139 xpos,ypos,scale);
140 sub.dump();
141 }
142 // }}}
143
convert_order(int subpage) const144 std::pair<int,int> NupState::convert_order(int subpage) const // {{{
145 {
146 int subx,suby;
147 if (param.first==Axis::X) {
148 subx=subpage%param.nupX;
149 suby=subpage/param.nupX;
150 } else {
151 subx=subpage/param.nupY;
152 suby=subpage%param.nupY;
153 }
154
155 subx=(param.nupX-1)*(param.xstart+1)/2-param.xstart*subx;
156 suby=(param.nupY-1)*(param.ystart+1)/2-param.ystart*suby;
157
158 return std::make_pair(subx,suby);
159 }
160 // }}}
161
lin(Position pos,float size)162 static inline float lin(Position pos,float size) // {{{
163 {
164 if (pos==-1) return 0;
165 else if (pos==0) return size/2;
166 else if (pos==1) return size;
167 return size*(pos+1)/2;
168 }
169 // }}}
170
calculate_edit(int subx,int suby,NupPageEdit & ret) const171 void NupState::calculate_edit(int subx,int suby,NupPageEdit &ret) const // {{{
172 {
173 // dimensions of a "nup cell"
174 const float width=param.width/param.nupX,
175 height=param.height/param.nupY;
176
177 // first calculate only for bottom-left corner
178 ret.xpos=subx*width;
179 ret.ypos=suby*height;
180
181 const float scalex=width/ret.sub.width,
182 scaley=height/ret.sub.height;
183 float subwidth=ret.sub.width*scaley,
184 subheight=ret.sub.height*scalex;
185
186 // TODO? if ( (!fitPlot)&&(ret.scale>1) ) ret.scale=1.0;
187 if (scalex>scaley) {
188 ret.scale=scaley;
189 subheight=height;
190 ret.xpos+=lin(param.xalign,width-subwidth);
191 } else {
192 ret.scale=scalex;
193 subwidth=width;
194 ret.ypos+=lin(param.yalign,height-subheight);
195 }
196
197 ret.sub.left=ret.xpos;
198 ret.sub.bottom=ret.ypos;
199 ret.sub.right=ret.sub.left+subwidth;
200 ret.sub.top=ret.sub.bottom+subheight;
201 }
202 // }}}
203
nextPage(float in_width,float in_height,NupPageEdit & ret)204 bool NupState::nextPage(float in_width,float in_height,NupPageEdit &ret) // {{{
205 {
206 in_pages++;
207 subpage++;
208 if (subpage>=nup) {
209 subpage=0;
210 out_pages++;
211 }
212
213 ret.sub.width=in_width;
214 ret.sub.height=in_height;
215
216 auto sub=convert_order(subpage);
217 calculate_edit(sub.first,sub.second,ret);
218
219 return (subpage==0);
220 }
221 // }}}
222
223
parsePosition(char a,char b)224 static std::pair<Axis,Position> parsePosition(char a,char b) // {{{ returns ,CENTER(0) on invalid
225 {
226 a|=0x20; // make lowercase
227 b|=0x20;
228 if ( (a=='l')&&(b=='r') ) {
229 return std::make_pair(Axis::X,Position::LEFT);
230 } else if ( (a=='r')&&(b=='l') ) {
231 return std::make_pair(Axis::X,Position::RIGHT);
232 } else if ( (a=='t')&&(b=='b') ) {
233 return std::make_pair(Axis::Y,Position::TOP);
234 } else if ( (a=='b')&&(b=='t') ) {
235 return std::make_pair(Axis::Y,Position::BOTTOM);
236 }
237 return std::make_pair(Axis::X,Position::CENTER);
238 }
239 // }}}
240
parseNupLayout(const char * val,NupParameters & ret)241 bool parseNupLayout(const char *val,NupParameters &ret) // {{{
242 {
243 assert(val);
244 auto pos0=parsePosition(val[0],val[1]);
245 if (pos0.second==CENTER) {
246 return false;
247 }
248 auto pos1=parsePosition(val[2],val[3]);
249 if ( (pos1.second==CENTER)||(pos0.first==pos1.first) ) {
250 return false;
251 }
252
253 ret.first=pos0.first;
254 if (ret.first==Axis::X) {
255 ret.xstart=pos0.second;
256 ret.ystart=pos1.second;
257 } else {
258 ret.xstart=pos1.second;
259 ret.ystart=pos0.second;
260 }
261
262 return (val[4]==0); // everything seen?
263 }
264 // }}}
265
266