Line data Source code
1 : /* Copyright (C) 2001-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * dercved from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include "cvundoes.h"
28 : #include "fontforgeui.h"
29 : #include "splineutil.h"
30 : #include <ustring.h>
31 : #include <gkeysym.h>
32 : #include <math.h>
33 :
34 : int gridfit_dpi=72, gridfit_depth=1; float gridfit_pointsizey=12, gridfit_pointsizex=12;
35 : int gridfit_x_sameas_y = true;
36 :
37 : static int last_fpgm = false;
38 :
39 0 : void SCDeGridFit(SplineChar *sc) {
40 : CharView *cv;
41 :
42 0 : for ( cv=(CharView *) (sc->views); cv!=NULL; cv=(CharView *) (cv->b.next) ) if ( cv->show_ft_results ) {
43 0 : SplinePointListsFree(cv->b.gridfit); cv->b.gridfit = NULL;
44 0 : FreeType_FreeRaster(cv->raster); cv->raster = NULL;
45 0 : cv->show_ft_results = false;
46 0 : GDrawRequestExpose(cv->v,NULL,false);
47 : }
48 0 : }
49 :
50 0 : void CVGridHandlePossibleFitChar(CharView *cv)
51 : {
52 0 : if( cv->show_ft_results_live_update )
53 0 : CVGridFitChar(cv);
54 0 : }
55 :
56 0 : void CVGridFitChar(CharView *cv) {
57 : void *single_glyph_context;
58 0 : SplineFont *sf = cv->b.sc->parent;
59 0 : int layer = CVLayer((CharViewBase *) cv);
60 :
61 0 : SplinePointListsFree(cv->b.gridfit); cv->b.gridfit = NULL;
62 0 : FreeType_FreeRaster(cv->raster); cv->raster = NULL;
63 :
64 0 : single_glyph_context = _FreeTypeFontContext(sf,cv->b.sc,NULL,layer,
65 0 : sf->layers[layer].order2?ff_ttf:ff_otf,0,NULL);
66 0 : if ( single_glyph_context==NULL ) {
67 0 : LogError(_("Freetype rasterization failed.\n") );
68 0 : return;
69 : }
70 :
71 0 : if ( cv->b.sc->layers[layer].refs!=NULL )
72 0 : SCNumberPoints(cv->b.sc,layer);
73 :
74 0 : cv->raster = FreeType_GetRaster(single_glyph_context,cv->b.sc->orig_pos,
75 0 : cv->ft_pointsizey, cv->ft_pointsizex, cv->ft_dpi, cv->ft_depth );
76 0 : cv->b.gridfit = FreeType_GridFitChar(single_glyph_context,cv->b.sc->orig_pos,
77 0 : cv->ft_pointsizey, cv->ft_pointsizex, cv->ft_dpi, &cv->b.ft_gridfitwidth,
78 0 : cv->b.sc, cv->ft_depth, true );
79 :
80 0 : FreeTypeFreeContext(single_glyph_context);
81 0 : GDrawRequestExpose(cv->v,NULL,false);
82 0 : if ( cv->b.sc->instructions_out_of_date && cv->b.sc->ttf_instrs_len!=0 )
83 0 : ff_post_notice(_("Instructions out of date"),
84 0 : _("The points have been changed. This may mean that the truetype instructions now refer to the wrong points and they may cause unexpected results."));
85 : }
86 :
87 0 : void SCReGridFit(SplineChar *sc,int layer) {
88 : CharView *cv;
89 :
90 0 : for ( cv=(CharView *) (sc->views); cv!=NULL; cv=(CharView *) (cv->b.next) ) if ( cv->show_ft_results ) {
91 0 : if ( cv->show_ft_results && CVLayer((CharViewBase *) cv)==layer ) {
92 0 : SplinePointListsFree(cv->b.gridfit); cv->b.gridfit = NULL;
93 0 : FreeType_FreeRaster(cv->raster); cv->raster = NULL;
94 0 : CVGridFitChar(cv);
95 : }
96 : }
97 0 : }
98 :
99 : #define CID_PointSize 1001
100 : #define CID_DPI 1002
101 : #define CID_Debugfpgm 1004
102 : #define CID_BW 1005
103 : #define CID_SameAs 1006
104 : #define CID_PointSizeX 1007
105 :
106 : typedef struct ftsizedata {
107 : unsigned int done: 1;
108 : unsigned int debug: 1;
109 : CharView *cv;
110 : GWindow gw;
111 : } FtSizeData;
112 :
113 0 : static int FtPpem_OK(GGadget *g, GEvent *e) {
114 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
115 0 : FtSizeData *fsd = GDrawGetUserData(GGadgetGetWindow(g));
116 : int _dpi, _depth;
117 : real ptsize, ptsizex;
118 0 : int err = 0;
119 0 : CharView *cv = fsd->cv;
120 :
121 0 : ptsize = GetReal8(fsd->gw,CID_PointSize,_("Pointsize Y"),&err);
122 0 : if ( GGadgetIsChecked(GWidgetGetControl(fsd->gw,CID_SameAs)) )
123 0 : ptsizex = ptsize;
124 : else
125 0 : ptsizex = GetReal8(fsd->gw,CID_PointSizeX,_("Pointsize X"),&err);
126 0 : _dpi = GetInt8(fsd->gw,CID_DPI,_("DPI"),&err);
127 0 : _depth = GGadgetIsChecked(GWidgetGetControl(fsd->gw,CID_BW)) ? 1 : 8;
128 0 : if ( err )
129 0 : return(true);
130 :
131 0 : last_fpgm = GGadgetIsChecked(GWidgetGetControl(fsd->gw,CID_Debugfpgm));
132 0 : cv->ft_pointsizey = ptsize; cv->ft_dpi = _dpi; cv->ft_depth = _depth;
133 0 : cv->ft_pointsizex = ptsizex;
134 0 : cv->ft_ppemy = rint(cv->ft_pointsizey*cv->ft_dpi/72.0);
135 0 : cv->ft_ppemx = rint(cv->ft_pointsizex*cv->ft_dpi/72.0);
136 :
137 0 : gridfit_dpi = _dpi; gridfit_pointsizey = ptsize; gridfit_depth = _depth;
138 0 : gridfit_pointsizex = ptsizex; gridfit_x_sameas_y = GGadgetIsChecked(GWidgetGetControl(fsd->gw,CID_SameAs));
139 0 : SavePrefs(true);
140 :
141 0 : SplinePointListsFree(cv->b.gridfit); cv->b.gridfit = NULL;
142 0 : FreeType_FreeRaster(cv->raster); cv->raster = NULL;
143 :
144 0 : if ( fsd->debug )
145 0 : CVDebugReInit(cv,true,last_fpgm);
146 : else {
147 0 : cv->show_ft_results = true;
148 0 : CVGridFitChar(cv);
149 : }
150 0 : CVLayersSet(cv);
151 0 : fsd->done = true;
152 0 : SCRefreshTitles(cv->b.sc);
153 : }
154 0 : return( true );
155 : }
156 :
157 0 : static int FtPpem_Cancel(GGadget *g, GEvent *e) {
158 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
159 0 : FtSizeData *fsd = GDrawGetUserData(GGadgetGetWindow(g));
160 0 : fsd->done = true;
161 : }
162 0 : return( true );
163 : }
164 :
165 0 : static int FtPpem_SameAsChanged(GGadget *g, GEvent *e) {
166 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
167 0 : FtSizeData *fsd = GDrawGetUserData(GGadgetGetWindow(g));
168 0 : if ( GGadgetIsChecked(g)) {
169 0 : const unichar_t *y = _GGadgetGetTitle(GWidgetGetControl(fsd->gw,CID_PointSize));
170 0 : GGadgetSetTitle(GWidgetGetControl(fsd->gw,CID_PointSizeX),y);
171 0 : GGadgetSetEnabled(GWidgetGetControl(fsd->gw,CID_PointSizeX),false);
172 : } else {
173 0 : GGadgetSetEnabled(GWidgetGetControl(fsd->gw,CID_PointSizeX),true);
174 : }
175 : }
176 0 : return( true );
177 : }
178 :
179 0 : static int FtPpem_PtYChanged(GGadget *g, GEvent *e) {
180 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
181 0 : FtSizeData *fsd = GDrawGetUserData(GGadgetGetWindow(g));
182 0 : if ( GGadgetIsChecked(GWidgetGetControl(fsd->gw,CID_SameAs))) {
183 0 : const unichar_t *y = _GGadgetGetTitle(g);
184 0 : GGadgetSetTitle(GWidgetGetControl(fsd->gw,CID_PointSizeX),y);
185 : }
186 : }
187 0 : return( true );
188 : }
189 :
190 0 : static int fsd_e_h(GWindow gw, GEvent *event) {
191 0 : if ( event->type==et_close ) {
192 0 : FtSizeData *hd = GDrawGetUserData(gw);
193 0 : hd->done = true;
194 0 : } else if ( event->type == et_char ) {
195 0 : return( false );
196 0 : } else if ( event->type == et_map ) {
197 : /* Above palettes */
198 0 : GDrawRaise(gw);
199 : }
200 0 : return( true );
201 : }
202 :
203 0 : void CVFtPpemDlg(CharView *cv,int debug) {
204 : GRect pos;
205 : GWindow gw;
206 : GWindowAttrs wattrs;
207 : GGadgetCreateData gcd[16], boxes[8];
208 : GTextInfo label[16];
209 : FtSizeData fsd;
210 : char buffer[20], buffer2[20], buffer3[20];
211 : GGadgetCreateData *varray[7][4], *barray[9], *harray1[3], *harray2[3], *harray3[3];
212 : int k,r;
213 :
214 0 : memset(&fsd,0,sizeof(fsd));
215 0 : fsd.cv = cv;
216 0 : fsd.debug = debug;
217 :
218 0 : memset(&wattrs,0,sizeof(wattrs));
219 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
220 0 : wattrs.event_masks = ~(1<<et_charup);
221 0 : wattrs.restrict_input_to_me = 1;
222 0 : wattrs.undercursor = 1;
223 0 : wattrs.cursor = ct_pointer;
224 0 : wattrs.utf8_window_title = _("Grid Fit Parameters");
225 0 : wattrs.is_dlg = true;
226 0 : pos.x = pos.y = 0;
227 0 : pos.width = GGadgetScale(GDrawPointsToPixels(NULL,190));
228 0 : pos.height = GDrawPointsToPixels(NULL,106);
229 0 : fsd.gw = gw = GDrawCreateTopWindow(NULL,&pos,fsd_e_h,&fsd,&wattrs);
230 :
231 0 : memset(&label,0,sizeof(label));
232 0 : memset(&gcd,0,sizeof(gcd));
233 0 : memset(&boxes,0,sizeof(boxes));
234 :
235 0 : k=r=0;
236 0 : label[k].text = (unichar_t *) _("Debug _fpgm/prep");
237 0 : label[k].text_is_1byte = true;
238 0 : label[k].text_in_resource = true;
239 0 : gcd[k].gd.label = &label[k];
240 0 : gcd[k].gd.pos.x = 80; gcd[k].gd.pos.y = 4;
241 0 : gcd[k].gd.flags = debug ? (gg_enabled|gg_visible) : 0;
242 0 : if ( last_fpgm )
243 0 : gcd[k].gd.flags |= gg_cb_on;
244 0 : gcd[k].gd.cid = CID_Debugfpgm;
245 0 : gcd[k++].creator = GCheckBoxCreate;
246 0 : varray[r][0] = &gcd[k-1]; varray[r][1] = GCD_ColSpan; varray[r][2] = GCD_ColSpan; varray[r++][3] = NULL;
247 :
248 0 : label[k].text = (unichar_t *) _("Scale X/Y the same");
249 0 : label[k].text_is_1byte = true;
250 0 : label[k].text_in_resource = true;
251 0 : gcd[k].gd.label = &label[k];
252 0 : gcd[k].gd.pos.x = 110; gcd[k].gd.pos.y = 17+5+6;
253 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
254 0 : if ( gridfit_x_sameas_y )
255 0 : gcd[k].gd.flags |= gg_cb_on;
256 0 : gcd[k].gd.cid = CID_SameAs;
257 0 : gcd[k].gd.handle_controlevent = FtPpem_SameAsChanged;
258 0 : gcd[k++].creator = GCheckBoxCreate;
259 0 : varray[r][0] = &gcd[k-1]; varray[r][1] = GCD_HPad10;
260 :
261 0 : label[k].text = (unichar_t *) _("_DPI:");
262 0 : label[k].text_is_1byte = true;
263 0 : label[k].text_in_resource = true;
264 0 : gcd[k].gd.label = &label[k];
265 0 : gcd[k].gd.pos.x = 110; gcd[k].gd.pos.y = 17+5+6;
266 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
267 0 : gcd[k++].creator = GLabelCreate;
268 0 : harray1[0] = &gcd[k-1];
269 :
270 0 : sprintf( buffer2, "%d", gridfit_dpi );
271 0 : label[k].text = (unichar_t *) buffer2;
272 0 : label[k].text_is_1byte = true;
273 0 : gcd[k].gd.label = &label[k];
274 0 : gcd[k].gd.pos.x = 140; gcd[k].gd.pos.y = 17+5; gcd[k].gd.pos.width = 40;
275 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
276 0 : gcd[k].gd.cid = CID_DPI;
277 0 : gcd[k++].creator = GTextFieldCreate;
278 0 : harray1[1] = &gcd[k-1]; harray1[2] = NULL;
279 :
280 0 : boxes[2].gd.flags = gg_enabled|gg_visible;
281 0 : boxes[2].gd.u.boxelements = harray1;
282 0 : boxes[2].creator = GHBoxCreate;
283 0 : varray[r][2] = &boxes[2]; varray[r++][3] = NULL;
284 :
285 0 : label[k].text = (unichar_t *) _("_Pointsize Y:");
286 0 : label[k].text_is_1byte = true;
287 0 : label[k].text_in_resource = true;
288 0 : gcd[k].gd.label = &label[k];
289 0 : gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = 17+5+6;
290 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
291 0 : gcd[k++].creator = GLabelCreate;
292 0 : harray2[0] = &gcd[k-1];
293 :
294 0 : sprintf( buffer, "%g", gridfit_pointsizey );
295 0 : label[k].text = (unichar_t *) buffer;
296 0 : label[k].text_is_1byte = true;
297 0 : gcd[k].gd.label = &label[k];
298 0 : gcd[k].gd.pos.x = 57; gcd[k].gd.pos.y = 17+5; gcd[k].gd.pos.width = 40;
299 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
300 0 : gcd[k].gd.handle_controlevent = FtPpem_PtYChanged;
301 0 : gcd[k].gd.cid = CID_PointSize;
302 0 : gcd[k++].creator = GTextFieldCreate;
303 0 : harray2[1] = &gcd[k-1]; harray2[2] = NULL;
304 :
305 0 : boxes[3].gd.flags = gg_enabled|gg_visible;
306 0 : boxes[3].gd.u.boxelements = harray2;
307 0 : boxes[3].creator = GHBoxCreate;
308 0 : varray[r][0] = &boxes[3]; varray[r][1] = GCD_HPad10;
309 :
310 0 : label[k].text = (unichar_t *) _("_X:");
311 0 : label[k].text_is_1byte = true;
312 0 : label[k].text_in_resource = true;
313 0 : gcd[k].gd.label = &label[k];
314 0 : gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = 17+5+6;
315 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
316 0 : gcd[k++].creator = GLabelCreate;
317 0 : harray3[0] = &gcd[k-1];
318 :
319 0 : sprintf( buffer3, "%g", gridfit_x_sameas_y ? gridfit_pointsizey : gridfit_pointsizex);
320 0 : label[k].text = (unichar_t *) buffer3;
321 0 : label[k].text_is_1byte = true;
322 0 : gcd[k].gd.label = &label[k];
323 0 : gcd[k].gd.pos.x = 57; gcd[k].gd.pos.y = 17+5; gcd[k].gd.pos.width = 40;
324 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
325 0 : if ( gridfit_x_sameas_y )
326 0 : gcd[k].gd.flags = gg_visible;
327 0 : gcd[k].gd.cid = CID_PointSizeX;
328 0 : gcd[k++].creator = GTextFieldCreate;
329 0 : harray3[1] = &gcd[k-1]; harray3[2] = NULL;
330 :
331 0 : boxes[4].gd.flags = gg_enabled|gg_visible;
332 0 : boxes[4].gd.u.boxelements = harray3;
333 0 : boxes[4].creator = GHBoxCreate;
334 0 : varray[r][2] = &boxes[4]; varray[r++][3] = NULL;
335 :
336 0 : label[k].text = (unichar_t *) _("_Mono");
337 0 : label[k].text_is_1byte = true;
338 0 : label[k].text_in_resource = true;
339 0 : gcd[k].gd.label = &label[k];
340 0 : gcd[k].gd.pos.x = 20; gcd[k].gd.pos.y = 14+31;
341 0 : gcd[k].gd.flags = gridfit_depth==1 ? (gg_enabled|gg_visible|gg_cb_on) : (gg_enabled|gg_visible);
342 0 : gcd[k].gd.cid = CID_BW;
343 0 : gcd[k++].creator = GRadioCreate;
344 0 : varray[r][0] = &gcd[k-1]; varray[r][1] = GCD_HPad10;
345 :
346 0 : label[k].text = (unichar_t *) _("_Anti-Aliased");
347 0 : label[k].text_is_1byte = true;
348 0 : label[k].text_in_resource = true;
349 0 : gcd[k].gd.label = &label[k];
350 0 : gcd[k].gd.pos.x = 80; gcd[k].gd.pos.y = gcd[9].gd.pos.y;
351 0 : gcd[k].gd.flags = gridfit_depth!=1 ? (gg_enabled|gg_visible|gg_cb_on) : (gg_enabled|gg_visible);
352 0 : gcd[k++].creator = GRadioCreate;
353 0 : varray[r][2] = &gcd[k-1]; varray[r++][3] = NULL;
354 :
355 0 : gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = 17+31+16;
356 0 : gcd[k].gd.pos.width = 190-10;
357 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
358 0 : gcd[k++].creator = GLineCreate;
359 0 : varray[r][0] = &gcd[k-1]; varray[r][1] = GCD_ColSpan; varray[r][2] = GCD_ColSpan; varray[r++][3] = NULL;
360 :
361 0 : gcd[k].gd.pos.x = 20-3; gcd[k].gd.pos.y = 17+37+16;
362 0 : gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0;
363 0 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
364 0 : label[k].text = (unichar_t *) _("_OK");
365 0 : label[k].text_is_1byte = true;
366 0 : label[k].text_in_resource = true;
367 0 : gcd[k].gd.mnemonic = 'O';
368 0 : gcd[k].gd.label = &label[k];
369 0 : gcd[k].gd.handle_controlevent = FtPpem_OK;
370 0 : gcd[k++].creator = GButtonCreate;
371 0 : barray[0] = GCD_Glue; barray[1] = &gcd[k-1]; barray[2] = GCD_Glue;
372 :
373 0 : gcd[k].gd.pos.x = -20; gcd[k].gd.pos.y = gcd[4].gd.pos.y+3;
374 0 : gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0;
375 0 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
376 0 : label[k].text = (unichar_t *) _("_Cancel");
377 0 : label[k].text_is_1byte = true;
378 0 : label[k].text_in_resource = true;
379 0 : gcd[k].gd.label = &label[k];
380 0 : gcd[k].gd.mnemonic = 'C';
381 0 : gcd[k].gd.handle_controlevent = FtPpem_Cancel;
382 0 : gcd[k++].creator = GButtonCreate;
383 0 : barray[3] = GCD_Glue; barray[4] = &gcd[k-1]; barray[5] = GCD_Glue; barray[6] = NULL;
384 :
385 0 : boxes[5].gd.flags = gg_enabled|gg_visible;
386 0 : boxes[5].gd.u.boxelements = barray;
387 0 : boxes[5].creator = GHBoxCreate;
388 0 : varray[r][0] = &boxes[5]; varray[r][1] = GCD_ColSpan; varray[r][2] = GCD_ColSpan; varray[r++][3] = NULL;
389 0 : varray[r][0] = NULL;
390 :
391 0 : boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
392 0 : boxes[0].gd.flags = gg_enabled|gg_visible;
393 0 : boxes[0].gd.u.boxelements = varray[0];
394 0 : boxes[0].creator = GHVGroupCreate;
395 :
396 :
397 0 : GGadgetsCreate(gw,boxes);
398 0 : GHVBoxFitWindow(boxes[0].ret);
399 :
400 0 : GWidgetIndicateFocusGadget(GWidgetGetControl(gw,CID_PointSize));
401 0 : GTextFieldSelect(GWidgetGetControl(gw,CID_PointSize),0,-1);
402 :
403 0 : GWidgetHidePalettes();
404 0 : GDrawSetVisible(gw,true);
405 0 : while ( !fsd.done )
406 0 : GDrawProcessOneEvent(NULL);
407 0 : GDrawDestroyWindow(gw);
408 0 : }
|