• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param) // {{{
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