Line data Source code
1 : /* Copyright (C) 2003-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 "splineorder2.h"
30 : #include "splineutil.h"
31 : #include <math.h>
32 : #include <gkeysym.h>
33 : #include <ustring.h>
34 : #include <gresource.h>
35 :
36 : extern GBox _ggadget_Default_Box;
37 : #define MAIN_FOREGROUND (_ggadget_Default_Box.main_foreground)
38 :
39 : int debug_wins = dw_registers|dw_stack;
40 :
41 : #ifndef FREETYPE_HAS_DEBUGGER
42 0 : void CVDebugReInit(CharView *cv,int restart_debug,int debug_fpgm) {
43 0 : }
44 :
45 0 : void CVDebugFree(DebugView *dv) {
46 0 : }
47 :
48 0 : int DVChar(DebugView *dv, GEvent *event) {
49 0 : return( false );
50 : }
51 :
52 0 : void CVDebugPointPopup(CharView *cv) {
53 0 : }
54 : #else
55 : #include <ft2build.h>
56 : #include FT_FREETYPE_H
57 : #include <internal/internal.h>
58 : #include "ttinterp.h"
59 :
60 : # define PPEMX(exc) ((exc)->size->root.metrics.x_ppem)
61 : # define PPEMY(exc) ((exc)->size->root.metrics.y_ppem)
62 :
63 : static Color rasterbackcol = 0xffffff;
64 :
65 : static int debuggercolsinited = false;
66 :
67 : static void DebugColInit( void ) {
68 : GResStruct debugcolors[] = {
69 : { "Background", rt_color, &rasterbackcol, NULL, 0 },
70 : GRESSTRUCT_EMPTY
71 : };
72 : if ( debuggercolsinited )
73 : return;
74 : rasterbackcol = GDrawGetDefaultBackground(screen_display);
75 : GResourceFind( debugcolors, "DVRaster.");
76 : debuggercolsinited = true;
77 : }
78 :
79 : static int DVBpCheck(struct instrinfo *ii, int ip) {
80 : DebugView *dv = (ii->userdata);
81 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
82 :
83 : if ( exc==NULL )
84 : return( false );
85 :
86 : return( DebuggerBpCheck( dv->dc,exc->curRange,ip));
87 : }
88 :
89 : static void DVToggleBp(struct instrinfo *ii, int ip) {
90 : DebugView *dv = (ii->userdata);
91 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
92 :
93 : if ( exc==NULL )
94 : return;
95 : DebuggerToggleBp(dv->dc,exc->curRange,ip);
96 : }
97 :
98 : static void DVRasterExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
99 : CharView *cv = dv->cv;
100 : int y,x,xem, yem;
101 : GRect r;
102 :
103 : GDrawGetSize(dv->raster,&r);
104 : GDrawFillRect(pixmap,&event->u.expose.rect,rasterbackcol);
105 : xem = cv->ft_ppemx;
106 : yem = cv->ft_ppemy;
107 : x = (r.width - xem)/2;
108 : y = (r.height - yem)/2 + yem*cv->b.sc->parent->ascent/(cv->b.sc->parent->ascent+cv->b.sc->parent->descent);
109 :
110 : GDrawDrawLine(pixmap,0,y,r.width,y,0xa0a0a0); /* Axes */
111 : GDrawDrawLine(pixmap,x,0,x,r.height,0xa0a0a0);
112 :
113 : if ( cv->raster!=NULL ) {
114 : GImage gi;
115 : struct _GImage base;
116 : GClut clut;
117 : int i;
118 :
119 : memset(&gi,'\0',sizeof(gi));
120 : memset(&base,'\0',sizeof(base));
121 : memset(&clut,'\0',sizeof(clut));
122 : gi.u.image = &base;
123 : base.clut = &clut;
124 : if ( cv->raster->num_greys<=2 ) {
125 : base.image_type = it_mono;
126 : clut.clut_len = 2;
127 : clut.clut[0] = rasterbackcol;
128 : clut.trans_index = 0;
129 : } else {
130 : base.image_type = it_index;
131 : clut.clut_len = 256;
132 : clut.clut[0] = rasterbackcol;
133 : for ( i=1; i<256; ++i ) {
134 : clut.clut[i] = ( (COLOR_RED(clut.clut[0])*(0xff-i)/0xff)<<16 ) |
135 : ( (COLOR_GREEN(clut.clut[0])*(0xff-i)/0xff)<<8 ) |
136 : ( (COLOR_BLUE(clut.clut[0])*(0xff-i)/0xff) );
137 : }
138 : clut.trans_index = 0;
139 : }
140 : base.data = cv->raster->bitmap;
141 : base.bytes_per_line = cv->raster->bytes_per_row;
142 : base.width = cv->raster->cols;
143 : base.height = cv->raster->rows;
144 : GDrawDrawImage(pixmap,&gi,NULL, x+cv->raster->lb,y-cv->raster->as);
145 : }
146 : }
147 :
148 : static void DVRegExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
149 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
150 : char buffer[100];
151 : int y;
152 :
153 : GDrawFillRect(pixmap,&event->u.expose.rect,GDrawGetDefaultBackground(screen_display));
154 : GDrawSetFont(pixmap,dv->ii.gfont);
155 : y = 3+dv->ii.as - dv->reg_offtop*dv->ii.fh;
156 :
157 : if ( exc==NULL ) {
158 : GDrawDrawText8(pixmap,3,y,"<not running>",-1,MAIN_FOREGROUND);
159 : return;
160 : }
161 :
162 : sprintf( buffer, " rp0: %d", exc->GS.rp0 );
163 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
164 : sprintf( buffer, " rp1: %d", exc->GS.rp1 );
165 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
166 : sprintf( buffer, " rp2: %d", exc->GS.rp2 );
167 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
168 : sprintf( buffer, "loop: %ld", exc->GS.loop );
169 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
170 : y+=2;
171 :
172 : sprintf( buffer, " zp0: %s", exc->GS.gep0?"Normal":"Twilight" );
173 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
174 : sprintf( buffer, " zp1: %s", exc->GS.gep1?"Normal":"Twilight" );
175 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
176 : sprintf( buffer, " zp2: %s", exc->GS.gep2?"Normal":"Twilight" );
177 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
178 : y+=2;
179 :
180 : sprintf( buffer, "MinDist: %.2f", exc->GS.minimum_distance/64.0 );
181 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
182 : sprintf( buffer, "CvtCutin: %.2f", exc->GS.control_value_cutin/64.0 );
183 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
184 : sprintf( buffer, "SingWidCut: %.2f", exc->GS.single_width_cutin/64.0 );
185 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
186 : sprintf( buffer, "SingWidVal: %.2f", exc->GS.single_width_value/64.0 );
187 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
188 : y+=2;
189 :
190 : sprintf( buffer, "freeVec: %g,%g", (((int)exc->GS.freeVector.x<<16)>>(16+14)) + ((exc->GS.freeVector.x&0x3fff)/16384.0),
191 : (((int)exc->GS.freeVector.y<<16)>>(16+14)) + ((exc->GS.freeVector.y&0x3fff)/16384.0) );
192 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
193 : sprintf( buffer, "projVec: %g,%g", (((int)exc->GS.projVector.x<<16)>>(16+14)) + ((exc->GS.projVector.x&0x3fff)/16384.0),
194 : (((int)exc->GS.projVector.y<<16)>>(16+14)) + ((exc->GS.projVector.y&0x3fff)/16384.0) );
195 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
196 : sprintf( buffer, "dualVec: %g,%g", (((int)exc->GS.dualVector.x<<16)>>(16+14)) + ((exc->GS.dualVector.x&0x3fff)/16384.0),
197 : (((int)exc->GS.dualVector.y<<16)>>(16+14)) + ((exc->GS.dualVector.y&0x3fff)/16384.0) );
198 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
199 : y+=2;
200 :
201 : sprintf( buffer, "AutoFlip: %s", exc->GS.auto_flip?"True": "False" );
202 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
203 : sprintf( buffer, "DeltaBase: %d", exc->GS.delta_base );
204 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
205 : sprintf( buffer, "DeltaShift: %d", exc->GS.delta_shift );
206 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
207 : sprintf( buffer, "RndState: %s",
208 : exc->GS.round_state==TT_Round_To_Half_Grid? "To Half Grid" :
209 : exc->GS.round_state==TT_Round_To_Grid? "To Grid" :
210 : exc->GS.round_state==TT_Round_To_Double_Grid? "To Double Grid" :
211 : exc->GS.round_state==TT_Round_Down_To_Grid? "Down To Grid" :
212 : exc->GS.round_state==TT_Round_Up_To_Grid? "Up To Grid" :
213 : exc->GS.round_state==TT_Round_Off? "Off" :
214 : exc->GS.round_state==TT_Round_Super? "Super" :
215 : exc->GS.round_state==TT_Round_Super_45? "Super45" :
216 : "Unknown" );
217 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
218 : sprintf( buffer, "SRndPeriod: %.2f", exc->period/64.0 );
219 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
220 : sprintf( buffer, "SRndPhase: %.2f", exc->phase/64.0 );
221 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
222 : sprintf( buffer, "SRndThreshold: %.2f", exc->threshold/64.0 );
223 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
224 : sprintf( buffer, "InstrControl: %d", exc->GS.instruct_control );
225 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
226 : sprintf( buffer, "ScanControl: %s", exc->GS.scan_control?"True": "False" );
227 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
228 : sprintf( buffer, "ScanType: %d", exc->GS.scan_type );
229 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
230 :
231 : /* Instruction control, scan control, scan type, phase, threshold for super rounding */
232 :
233 : y += 2;
234 : sprintf( buffer, "Pixels/Em: %d", PPEMY(exc) );
235 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
236 : }
237 :
238 : static void DVStackExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
239 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
240 : char buffer[100];
241 : int i, y;
242 :
243 : GDrawFillRect(pixmap,&event->u.expose.rect,GDrawGetDefaultBackground(screen_display));
244 : GDrawSetFont(pixmap,dv->ii.gfont);
245 : y = 3+dv->ii.as - dv->stack_offtop*dv->ii.fh;
246 : if ( exc==NULL || exc->top==0 ) {
247 : GDrawDrawText8(pixmap,3,y,"<empty>",-1,MAIN_FOREGROUND);
248 : } else {
249 : for ( i=exc->top-1; i>=0; --i ) {
250 : sprintf(buffer, "%3d: %3ld (%.2f)", i, exc->stack[i], exc->stack[i]/64.0 );
251 : GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND);
252 : if ( y>event->u.expose.rect.y+event->u.expose.rect.height )
253 : break;
254 : y += dv->ii.fh;
255 : }
256 : }
257 : }
258 :
259 : static void DVStorageExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
260 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
261 : char buffer[100];
262 : int i, y;
263 :
264 : GDrawFillRect(pixmap,&event->u.expose.rect,GDrawGetDefaultBackground(screen_display));
265 : GDrawSetFont(pixmap,dv->ii.gfont);
266 : y = 3+dv->ii.as - dv->storage_offtop*dv->ii.fh;
267 : if ( exc==NULL || exc->storeSize==0 ) {
268 : GDrawDrawText8(pixmap,3,y,_("<empty>"),-1,MAIN_FOREGROUND);
269 : } else {
270 : int n_watch;
271 : uint8 *watches = DebuggerGetWatchStores(dv->dc,&n_watch);
272 : for ( i=0; i<exc->storeSize; ++i ) {
273 : if ( !DebuggerIsStorageSet(dv->dc,i) )
274 : sprintf( buffer, _("%3d: <uninitialized>"), i );
275 : else
276 : sprintf(buffer, "%3d: %3ld (%.2f)", i, exc->storage[i], exc->storage[i]/64.0 );
277 : if ( i<n_watch && watches!=NULL && watches[i] && y>0 )
278 : GDrawDrawImage(pixmap,&GIcon_Stop,NULL,3,
279 : y-dv->ii.as-2);
280 : GDrawDrawText8(pixmap,23,y,buffer,-1,MAIN_FOREGROUND);
281 : if ( y>event->u.expose.rect.y+event->u.expose.rect.height )
282 : break;
283 : y += dv->ii.fh;
284 : }
285 : }
286 : }
287 :
288 : static void DVCvtExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
289 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
290 : char buffer[100];
291 : int i, y;
292 :
293 : GDrawFillRect(pixmap,&event->u.expose.rect,GDrawGetDefaultBackground(screen_display));
294 : GDrawSetFont(pixmap,dv->ii.gfont);
295 : y = 3+dv->ii.as;
296 : if ( exc==NULL || exc->cvtSize==0 ) {
297 : GDrawDrawText8(pixmap,3,y,_("<empty>"),-1,MAIN_FOREGROUND);
298 : } else {
299 : int n_watch;
300 : uint8 *watches = DebuggerGetWatchCvts(dv->dc,&n_watch);
301 : for ( i=0; dv->cvt_offtop+i<exc->cvtSize; ++i ) {
302 : sprintf(buffer, "%3d: %3ld (%.2f)", dv->cvt_offtop+i,
303 : exc->cvt[dv->cvt_offtop+i], exc->cvt[dv->cvt_offtop+i]/64.0 );
304 : if ( dv->cvt_offtop+i<n_watch && watches!=NULL && watches[dv->cvt_offtop+i] && y>0 )
305 : GDrawDrawImage(pixmap,&GIcon_Stop,NULL,3,
306 : y-dv->ii.as-2);
307 : GDrawDrawText8(pixmap,23,y,buffer,-1,MAIN_FOREGROUND);
308 : if ( y>event->u.expose.rect.y+event->u.expose.rect.height )
309 : break;
310 : y += dv->ii.fh;
311 : }
312 : }
313 : }
314 :
315 : static void ScalePoint(BasePoint *me,FT_Vector *cur,real scalex, real scaley,struct reflist *a) {
316 : double x,y,temp, offx, offy;
317 :
318 : x = cur->x*scalex;
319 : y = cur->y*scaley;
320 : while ( a!=NULL ) {
321 : RefChar *r = a->ref;
322 : a = a->parent;
323 : temp = r->transform[0]*x + r->transform[2]*y;
324 : y = r->transform[1]*x + r->transform[3]*y;
325 : x = temp;
326 : offx = r->transform[4];
327 : offy = r->transform[5];
328 : if ( r->round_translation_to_grid ) {
329 : offx = rint(offx/(scalex*64))*scalex*64;
330 : offy = rint(offy/(scaley*64))*scaley*64;
331 : }
332 : x += offx; y += offy;
333 : }
334 : me->x = x;
335 : me->y = y;
336 : }
337 :
338 : #define CID_Twilight 1001
339 : #define CID_Normal 1002
340 : #define CID_Grid 1003
341 : #define CID_EmUnit 1004
342 : #define CID_Raw 1005
343 : #define CID_Current 1006
344 : #define CID_Original 1007
345 : #define CID_Transform 1008
346 : static int show_twilight = false, show_grid=true, show_current=true, show_transformed=true, show_raw=false;
347 :
348 : static void DVPointsVExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
349 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
350 : char buffer[100];
351 : int i, l, y, c;
352 : FT_Vector *pts;
353 : int n, n_watch, ph;
354 : TT_GlyphZoneRec *r;
355 : uint8 *watches;
356 : BasePoint me,me2;
357 : struct reflist *actives;
358 :
359 : GDrawFillRect(pixmap,&event->u.expose.rect,GDrawGetDefaultBackground(screen_display));
360 : y = 3+dv->ii.as-dv->points_offtop*dv->ii.fh;
361 : if ( exc==NULL )
362 : n = 0;
363 : else {
364 : show_twilight = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Twilight));
365 : show_grid = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Grid));
366 : #if defined(FONTFORGE_CONFIG_SHOW_RAW_POINTS)
367 : show_raw = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Raw));
368 : #endif
369 : if ( !show_raw )
370 : show_transformed = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Transform));
371 : show_current = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Current));
372 : r = show_twilight ? &exc->twilight : &exc->pts;
373 : n = r->n_points;
374 : pts = show_current ? r->cur : r->org;
375 : c = 0;
376 : ph = FreeTypeAtLeast(2,1,8)?4:2; /* number of phantom pts */
377 :
378 : actives = dv->active_refs;
379 : if ( !show_transformed || show_raw )
380 : actives = NULL;
381 :
382 : watches = DebuggerGetWatches(dv->dc,&n_watch);
383 :
384 : GDrawSetFont(pixmap,dv->ii.gfont);
385 : for ( i=0; i<n; ++i ) {
386 : if ( i==0 ) l=n-ph; else l=i-1; /* Skip 4 phantom points */
387 : if ( !show_twilight && i<n-ph &&
388 : !(r->tags[i]&FT_Curve_Tag_On) && !(r->tags[l]&FT_Curve_Tag_On)) {
389 : ScalePoint(&me,&pts[i],dv->scalex,dv->scaley,actives);
390 : ScalePoint(&me2,&pts[l],dv->scalex,dv->scaley,actives);
391 : me.x = (me.x+me2.x)/2; me.y = (me.y+me2.y)/2;
392 : if ( show_grid )
393 : sprintf(buffer, " : I %.2f,%.2f",
394 : (double) (me.x/dv->scalex/64.0), (double) (me.y/dv->scaley/64.0) );
395 : else if ( show_raw )
396 : sprintf(buffer, " : I %g,%g",
397 : (double) ((pts[i].x+pts[l].x)/2.0), (double) ((pts[i].y+pts[l].y)/2.0) );
398 : else
399 : sprintf(buffer, " : I %g,%g", (double) me.x , (double) me.y );
400 : if ( y>0 )
401 : GDrawDrawText8(pixmap,3+19,y,buffer,-1,MAIN_FOREGROUND);
402 : y += dv->ii.fh;
403 : }
404 : if ( r->contours!=NULL && i==r->contours[c] ) { /* No contours in twilight */
405 : ++c;
406 : GDrawDrawLine(pixmap,0,y+dv->ii.fh-dv->ii.as,
407 : event->u.expose.rect.x+event->u.expose.rect.width,y+dv->ii.fh-dv->ii.as,
408 : 0x000000);
409 : }
410 : if ( i<n_watch && !show_twilight && watches!=NULL && watches[i] && y>0 )
411 : GDrawDrawImage(pixmap,&GIcon_Stop,NULL,3,
412 : y-dv->ii.as-2);
413 : ScalePoint(&me,&pts[i],dv->scalex,dv->scaley,actives);
414 : if ( show_grid )
415 : sprintf(buffer, "%3d: %c%c%c %.2f,%.2f", i,
416 : show_twilight ? 'T' : i>=n-ph? 'F' : r->tags[i]&FT_Curve_Tag_On?'P':'C',
417 : r->tags[i]&FT_Curve_Tag_Touch_X?'X':' ', r->tags[i]&FT_Curve_Tag_Touch_Y?'Y':' ',
418 : (double) (me.x/dv->scalex/64.0), (double) (me.y/dv->scaley/64.0) );
419 : else if ( show_raw )
420 : sprintf(buffer, "%3d: %c%c%c %d,%d", i,
421 : r->tags[i]&FT_Curve_Tag_On?'P':'C', r->tags[i]&FT_Curve_Tag_Touch_X?'X':' ', r->tags[i]&FT_Curve_Tag_Touch_Y?'Y':' ',
422 : (int) pts[i].x, (int) pts[i].y );
423 : else
424 : sprintf(buffer, "%3d: %c%c%c %g,%g", i,
425 : r->tags[i]&FT_Curve_Tag_On?'P':'C', r->tags[i]&FT_Curve_Tag_Touch_X?'X':' ', r->tags[i]&FT_Curve_Tag_Touch_Y?'Y':' ',
426 : (double) me.x, (double) me.y );
427 : if ( y>0 )
428 : GDrawDrawText8(pixmap,3+19,y,buffer,-1,MAIN_FOREGROUND);
429 : if ( y>event->u.expose.rect.y+event->u.expose.rect.height )
430 : break;
431 : y += dv->ii.fh;
432 : }
433 : }
434 : if ( n==0 ) {
435 : GDrawDrawText8(pixmap,3,y,_("<none>"),-1,MAIN_FOREGROUND);
436 : }
437 : }
438 :
439 : static void DVPointsExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
440 : GDrawSetLineWidth(pixmap,0);
441 : GDrawDrawLine(pixmap,event->u.expose.rect.x,dv->pts_head-1,event->u.expose.rect.x+event->u.expose.rect.width,dv->pts_head-1,0x000000);
442 : }
443 :
444 : static SplineSet *ContourFromPoint(TT_GlyphZoneRec *pts, real scalex, real scaley,int i,
445 : SplineSet *last, struct reflist *actives ) {
446 : SplineSet *cur;
447 : SplinePoint *sp;
448 : BasePoint me;
449 :
450 : ScalePoint(&me,&pts->cur[i],scalex,scaley,actives);
451 :
452 : sp = SplinePointCreate(me.x,me.y);
453 : sp->ttfindex = i;
454 : cur = chunkalloc(sizeof(SplineSet));
455 : if ( last!=NULL )
456 : last->next = cur;
457 : cur->first = cur->last = sp;
458 : return( cur );
459 : }
460 :
461 : static SplineSet *SplineSetsFromPoints(TT_GlyphZoneRec *pts, real scalex, real scaley,
462 : struct reflist *actives) {
463 : int i=0, c, last_off, start;
464 : SplineSet *head=NULL, *last=NULL, *cur;
465 : SplinePoint *sp;
466 : BasePoint me, me2;
467 : /* very similar to parsettf.c: ttfbuildcontours */
468 :
469 : for ( c=0; c<pts->n_contours; ++c ) {
470 : if ( pts->contours[c]<i ) /* Sigh. Yes there are fonts with bad endpt info */
471 : continue;
472 : cur = chunkalloc(sizeof(SplineSet));
473 : if ( head==NULL )
474 : head = cur;
475 : else
476 : last->next = cur;
477 : last = cur;
478 : last_off = false;
479 : start = i;
480 : while ( i<=pts->contours[c] && i<pts->n_points ) {
481 : if ( pts->tags[i]&FT_Curve_Tag_On ) {
482 : ScalePoint(&me,&pts->cur[i],scalex,scaley,actives);
483 : sp = SplinePointCreate(me.x,me.y);
484 : sp->ttfindex = i;
485 : if ( last_off && cur->last!=NULL ) {
486 : ScalePoint(&cur->last->nextcp,&pts->cur[i-1],scalex,scaley,actives);
487 : sp->prevcp = cur->last->nextcp;
488 : cur->last->nonextcp = false;
489 : cur->last->nextcpindex = i-1;
490 : sp->noprevcp = false;
491 : }
492 : last_off = false;
493 : } else if ( last_off ) {
494 : ScalePoint(&me,&pts->cur[i],scalex,scaley,actives);
495 : ScalePoint(&me2,&pts->cur[i-1],scalex,scaley,actives);
496 : sp = SplinePointCreate((me.x+me2.x)/2, (me.y+me2.y)/2 );
497 : sp->noprevcp = false;
498 : sp->ttfindex = 0xffff;
499 : if ( last_off && cur->last!=NULL ) {
500 : cur->last->nextcp = sp->prevcp = me2;
501 : cur->last->nonextcp = false;
502 : cur->last->nextcpindex = i-1;
503 : }
504 : /* last_off continues to be true */
505 : } else {
506 : last_off = true;
507 : sp = NULL;
508 : }
509 : if ( sp!=NULL ) {
510 : if ( cur->first==NULL )
511 : cur->first = sp;
512 : else
513 : SplineMake2(cur->last,sp);
514 : cur->last = sp;
515 : }
516 : ++i;
517 : }
518 : if ( start==i-1 ) {
519 : /* Single point contours (probably for positioning components, etc.) */
520 : ScalePoint(&me,&pts->cur[start],scalex,scaley,actives);
521 : sp = SplinePointCreate(me.x,me.y);
522 : sp->ttfindex = i-1;
523 : cur->first = cur->last = sp;
524 : } else if ( !(pts->tags[start]&FT_Curve_Tag_On) && !(pts->tags[i-1]&FT_Curve_Tag_On) ) {
525 : ScalePoint(&me,&pts->cur[start],scalex,scaley,actives);
526 : ScalePoint(&me2,&pts->cur[i-1],scalex,scaley,actives);
527 : sp = SplinePointCreate((me.x+me2.x)/2 , (me.y+me2.y)/2);
528 : sp->noprevcp = sp->nonextcp = false;
529 : cur->last->nextcp = sp->prevcp = me2;
530 : SplineMake2(cur->last,sp);
531 : cur->last = sp;
532 : cur->last->nextcp = cur->first->prevcp = me;
533 : cur->first->noprevcp = false;
534 : cur->last->nextcpindex = start;
535 : } else if ( !(pts->tags[i-1]&FT_Curve_Tag_On)) {
536 : ScalePoint(&me,&pts->cur[i-1],scalex,scaley,actives);
537 : cur->last->nextcp = cur->first->prevcp = me;
538 : cur->last->nonextcp = cur->first->noprevcp = false;
539 : cur->last->nextcpindex = i-1;
540 : } else if ( !(pts->tags[start]&FT_Curve_Tag_On) ) {
541 : ScalePoint(&me,&pts->cur[start],scalex,scaley,actives);
542 : cur->last->nextcp = cur->first->prevcp = me;
543 : cur->last->nonextcp = cur->first->noprevcp = false;
544 : cur->last->nextcpindex = start;
545 : }
546 : if ( cur->last!=cur->first ) {
547 : SplineMake2(cur->last,cur->first);
548 : cur->last = cur->first;
549 : }
550 : }
551 : if ( i+1<pts->n_points ) {
552 : /* depending on the version of freetype there should be either 2 or 4 */
553 : /* metric phantom points (2 horizontal metrics + 2 vertical metrics) */
554 : last = ContourFromPoint(pts,scalex,scaley,i,last,actives);
555 : if ( head==NULL ) head = last;
556 : last = ContourFromPoint(pts,scalex,scaley,i+1,last,actives);
557 : if ( i+3<pts->n_points ) {
558 : last = ContourFromPoint(pts,scalex,scaley,i+2,last,actives);
559 : last = ContourFromPoint(pts,scalex,scaley,i+3,last,actives);
560 : }
561 : }
562 : return( head );
563 : }
564 :
565 : static int DVStackTestSB(DebugView *dv, TT_ExecContext exc) {
566 : int min, max, page, offtop;
567 : GRect size;
568 : int top = exc==NULL ? 1 : exc->top;
569 :
570 : GScrollBarGetBounds(dv->stacksb,&min,&max,&page);
571 : GGadgetGetSize(dv->stacksb,&size);
572 : size.height /= dv->ii.fh;
573 : if ( max!=top || page!=size.height ) {
574 : GScrollBarSetBounds(dv->stacksb,0,top,size.height);
575 : offtop = dv->stack_offtop;
576 : if ( offtop+size.height > top )
577 : offtop = top-size.height;
578 : if ( offtop < 0 )
579 : offtop = 0;
580 : if ( offtop!=dv->stack_offtop ) {
581 : dv->stack_offtop = offtop;
582 : GScrollBarSetPos(dv->stacksb,dv->stack_offtop);
583 : return( true );
584 : }
585 : }
586 : return( false );
587 : }
588 :
589 : static int SameInstructionSet(DebugView *dv,TT_ExecContext exc) {
590 : /* This is a guessing game. It's easy enough to detect when we call a */
591 : /* subroutine, but detecting changing glyphs in a composite glyph is */
592 : /* much harder */
593 : int i;
594 :
595 : if ( dv->id.instrs!=(uint8 *) exc->code )
596 : return( false ); /* We called (or returned from) a subroutine */
597 :
598 : if ( dv->codeSize != exc->codeSize )
599 : return( false ); /* A glyph with a different number of instrs has been copied into the glyph instr area */
600 :
601 : for ( i=0 ; i<sizeof(dv->initialbytes) && i<dv->codeSize; ++i )
602 : if ( dv->initialbytes[i] != ((uint8 *) exc->code)[i] )
603 : return( false );
604 :
605 : return( true ); /* As best we can tell... */
606 : }
607 :
608 : static struct reflist *ARFindBase(SplineChar *sc,struct reflist *parent,int layer) {
609 : struct reflist *ret, *temp;
610 : RefChar *ref;
611 :
612 : if ( sc->layers[layer].splines!=NULL ||
613 : sc->layers[layer].refs==NULL )
614 : return( parent );
615 : ret = chunkalloc(sizeof(struct reflist));
616 : ret->parent = parent;
617 : for ( ref = sc->layers[layer].refs; ref!=NULL; ref=ref->next ) {
618 : ret->ref = ref;
619 : temp = ARFindBase(ref->sc,ret,layer);
620 : if ( temp!=ret )
621 : return( temp );
622 : if ( ref->sc->ttf_instrs_len!=0 )
623 : return( ret );
624 : }
625 : chunkfree(ret,sizeof(struct reflist));
626 : return( parent );
627 : }
628 :
629 : static void DVPointsFigureSB(DebugView *dv);
630 :
631 : static void ChangeCode(DebugView *dv,TT_ExecContext exc) {
632 : int i;
633 :
634 : dv->id.instrs =(uint8 *) exc->code;
635 : dv->id.instr_cnt = exc->codeSize;
636 : IIReinit(&dv->ii,exc->IP);
637 : dv->codeSize = exc->codeSize;
638 : dv->last_npoints = exc->pts.n_points;
639 : for ( i=0 ; i<sizeof(dv->initialbytes) && i<dv->codeSize; ++i )
640 : dv->initialbytes[i] = ((uint8 *) exc->code)[i];
641 :
642 : if ( dv->active_refs==NULL )
643 : dv->active_refs = ARFindBase(dv->cv->b.sc,NULL,dv->layer);
644 : else {
645 : struct reflist *temp;
646 : while ( dv->active_refs!=NULL ) {
647 : dv->active_refs->ref = dv->active_refs->ref->next;
648 : if ( dv->active_refs->ref==NULL ) {
649 : temp = dv->active_refs;
650 : dv->active_refs = temp->parent;
651 : chunkfree(temp,sizeof(struct reflist));
652 : if ( dv->active_refs==NULL ) {
653 : if ( dv->cv->b.sc->ttf_instrs_len!=0 )
654 : break;
655 : dv->active_refs = ARFindBase(dv->cv->b.sc,NULL,dv->layer);
656 : break;
657 : } else if ( dv->active_refs->ref->sc->ttf_instrs_len!=0 )
658 : break;
659 : else
660 : continue;
661 : }
662 : temp = ARFindBase(dv->active_refs->ref->sc,dv->active_refs,dv->layer);
663 : if ( temp!=dv->active_refs ) {
664 : dv->active_refs = temp;
665 : break;
666 : }
667 : if ( temp->ref->sc->ttf_instrs_len!=0 )
668 : break;
669 : }
670 : }
671 : if ( dv->points!=NULL )
672 : DVPointsFigureSB(dv);
673 : }
674 :
675 : static void DVFigureNewState(DebugView *dv,TT_ExecContext exc) {
676 : int range = exc==NULL ? cr_none : exc->curRange;
677 : CharView *cv = dv->cv;
678 :
679 : /* Code to look for proper function/idef rather than the full fpgm table */
680 : if ( exc==NULL ) {
681 : dv->id.instrs = NULL;
682 : dv->id.instr_cnt = 0;
683 : IIReinit(&dv->ii,-1);
684 : if ( cv->oldraster!=NULL )
685 : FreeType_FreeRaster(cv->oldraster);
686 : cv->oldraster = NULL;
687 : } else if ( !SameInstructionSet(dv,exc) || dv->last_npoints!=exc->pts.n_points ) {
688 : ChangeCode(dv,exc);
689 : } else
690 : IIScrollTo(&dv->ii,exc->IP,true);
691 :
692 : /* We might ask for a fractional number of pixels for an em. Freetype */
693 : /* isn't going to give us that, it rounds. Rather than guess how it does */
694 : /* that, let's just ask it... */
695 : /* The exact size is: cv->ft_pointsize*cv->ft_dpi/72.0 */
696 : /* Rounded size is: exc->size->root.metrics.x_ppem (or y_ppem) */
697 : if ( exc!=NULL ) {
698 : dv->scalex = (cv->b.sc->parent->ascent+cv->b.sc->parent->descent)/((double) PPEMX(exc)) / (1<<6);
699 : dv->scaley = (cv->b.sc->parent->ascent+cv->b.sc->parent->descent)/((double) PPEMY(exc)) / (1<<6);
700 : }
701 : if ( cv!=NULL && cv->coderange!=range ) {
702 : cv->coderange = range;
703 : CVInfoDraw(cv,cv->gw);
704 : }
705 :
706 : if ( exc!=NULL ) {
707 : if ( cv->oldraster!=NULL )
708 : FreeType_FreeRaster(cv->oldraster);
709 : cv->oldraster = cv->raster;
710 : SplinePointListsFree(cv->b.gridfit);
711 : cv->b.gridfit = SplineSetsFromPoints(&exc->pts,dv->scalex,dv->scaley,dv->active_refs);
712 : DVMarkPts(dv,cv->b.gridfit);
713 : cv->raster = DebuggerCurrentRaster(exc,cv->ft_depth);
714 : if ( show_transformed && !show_raw && cv->raster!=NULL ) {
715 : BasePoint me;
716 : FT_Vector cur;
717 : cur.y = cv->raster->as * 64;
718 : cur.x = cv->raster->lb * 64;
719 : ScalePoint(&me,&cur,dv->scalex,dv->scaley,dv->active_refs);
720 : cv->raster->lb = rint(me.x/dv->scalex/64);
721 : cv->raster->as = rint(me.y/dv->scaley/64);
722 : }
723 : if ( exc->pts.n_points<=2 )
724 : cv->b.ft_gridfitwidth = 0;
725 : /* suport for vertical phantom pts */
726 : else if ( FreeTypeAtLeast(2,1,8))
727 : cv->b.ft_gridfitwidth = exc->pts.cur[exc->pts.n_points-3].x * dv->scalex;
728 : else
729 : cv->b.ft_gridfitwidth = exc->pts.cur[exc->pts.n_points-1].x * dv->scalex;
730 : }
731 :
732 : if ( cv!=NULL )
733 : GDrawRequestExpose(cv->v,NULL,false);
734 : if ( dv->regs!=NULL )
735 : GDrawRequestExpose(dv->regs,NULL,false);
736 : if ( dv->stack!=NULL ) {
737 : DVStackTestSB(dv,exc);
738 : GDrawRequestExpose(dv->stack,NULL,false);
739 : }
740 : if ( dv->storage!=NULL )
741 : GDrawRequestExpose(dv->storage,NULL,false);
742 : if ( dv->cvt!=NULL )
743 : GDrawRequestExpose(dv->cvt,NULL,false);
744 : if ( dv->points!=NULL )
745 : GDrawRequestExpose(dv->points_v,NULL,false);
746 : if ( dv->raster!=NULL )
747 : GDrawRequestExpose(dv->raster,NULL,false);
748 : if ( dv->gloss!=NULL )
749 : GDrawRequestExpose(dv->gloss,NULL,false);
750 : }
751 :
752 : /* If a glyph has no instructions, it has no execcontext. But it is still */
753 : /* consistent to provide a current rasterization view (of the non-grid fit */
754 : /* splines) */
755 : static void DVDefaultRaster(DebugView *dv) {
756 : CharView *cv = dv->cv;
757 : void *single_glyph_context;
758 : SplineFont *sf = cv->b.sc->parent;
759 : int layer = CVLayer((CharViewBase *) cv);
760 :
761 : if ( cv->oldraster!=NULL )
762 : FreeType_FreeRaster(cv->oldraster);
763 : cv->oldraster = cv->raster;
764 : SplinePointListsFree(cv->b.gridfit);
765 : cv->b.gridfit = NULL;
766 : single_glyph_context = _FreeTypeFontContext(sf,cv->b.sc,NULL,layer,
767 : cv->b.sc->layers[layer].order2?ff_ttf:ff_otf,0,NULL);
768 : if ( single_glyph_context!=NULL ) {
769 : cv->raster = FreeType_GetRaster(single_glyph_context,cv->b.sc->orig_pos,
770 : cv->ft_pointsizey, cv->ft_pointsizex, cv->ft_dpi, cv->ft_depth );
771 : FreeTypeFreeContext(single_glyph_context);
772 : }
773 : cv->b.ft_gridfitwidth = 0;
774 :
775 : if ( cv->v!=NULL )
776 : GDrawRequestExpose(cv->v,NULL,false);
777 : if ( dv->raster!=NULL )
778 : GDrawRequestExpose(dv->raster,NULL,false);
779 : }
780 :
781 : static void DVGoFigure(DebugView *dv,enum debug_gotype go) {
782 : DebuggerGo(dv->dc,go,dv);
783 : DVFigureNewState(dv,DebuggerGetEContext(dv->dc));
784 : }
785 :
786 : static int DV_Run(GGadget *g, GEvent *e) {
787 : DebugView *dv;
788 :
789 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
790 : dv = GDrawGetUserData(GGadgetGetWindow(g));
791 : DVGoFigure(dv,(enum debug_gotype) GGadgetGetCid(g));
792 : }
793 : return( true );
794 : }
795 :
796 : static int DV_WatchPnt(GGadget *g, GEvent *e) {
797 : DebugView *dv;
798 : int pnum=0, n, any=0;
799 : SplineSet *ss;
800 : SplinePoint *sp;
801 : uint8 *watches;
802 :
803 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
804 : dv = GDrawGetUserData(GGadgetGetWindow(g));
805 : if ( dv->cv->b.layerheads[dv->cv->b.drawmode]->refs!=NULL ) {
806 : ff_post_error(_("No Watch Points"),_("Watch Points not supported in glyphs with references"));
807 : return( true );
808 : }
809 :
810 : DebuggerGetWatches(dv->dc,&n);
811 : watches = calloc(n,sizeof(uint8));
812 :
813 : for ( ss = dv->cv->b.layerheads[dv->cv->b.drawmode]->splines; ss!=NULL; ss=ss->next ) {
814 : for ( sp=ss->first; ; ) {
815 : sp->watched = false;
816 : if ( sp->ttfindex == 0xffff )
817 : /* Ignore it */;
818 : else if ( sp->selected && sp->ttfindex<n) {
819 : watches[pnum=sp->ttfindex] = true;
820 : any = true;
821 : sp->watched = true;
822 : }
823 : if ( !sp->nonextcp ) {
824 : ++pnum;
825 : if ( sp==dv->cv->p.sp && dv->cv->p.nextcp && pnum<n )
826 : watches[pnum] = true;
827 : }
828 : if ( sp->next==NULL )
829 : break;
830 : sp = sp->next->to;
831 : if ( sp==ss->first )
832 : break;
833 : }
834 : }
835 : if ( !any ) {
836 : free(watches);
837 : watches = NULL;
838 : }
839 : DebuggerSetWatches(dv->dc,n,watches);
840 : GDrawRequestExpose(dv->cv->v,NULL,false);
841 : if ( dv->points!=NULL )
842 : GDrawRequestExpose(dv->points_v,NULL,false);
843 : }
844 : return( true );
845 : }
846 :
847 : #define MID_Registers 1001
848 : #define MID_Stack 1002
849 : #define MID_Storage 1003
850 : #define MID_Points 1004
851 : #define MID_Cvt 1005
852 : #define MID_Raster 1006
853 : #define MID_Gloss 1007
854 :
855 : static void DVCreateRegs(DebugView *dv);
856 : static void DVCreateStack(DebugView *dv);
857 : static void DVCreateStore(DebugView *dv);
858 : static void DVCreatePoints(DebugView *dv);
859 : static void DVCreateCvt(DebugView *dv);
860 : static void DVCreateRaster(DebugView *dv);
861 :
862 : static struct { int flag; void (*create)(DebugView *); } wcreat[] = {
863 : {dw_registers, DVCreateRegs},
864 : {dw_stack, DVCreateStack},
865 : {dw_storage, DVCreateStore},
866 : {dw_points, DVCreatePoints},
867 : {dw_cvt, DVCreateCvt},
868 : {dw_raster, DVCreateRaster},
869 : {dw_gloss, DVCreateGloss},
870 : { 0, NULL }
871 : };
872 :
873 : static void DVMenuCreate(GWindow v, GMenuItem *mi,GEvent *e) {
874 : DebugView *dv = (DebugView *) GDrawGetUserData(v);
875 :
876 : if ( (&dv->regs)[mi->mid-MID_Registers]==NULL ) {
877 : (wcreat[mi->mid-MID_Registers].create)(dv);
878 : debug_wins |= wcreat[mi->mid-MID_Registers].flag;
879 : } else {
880 : GDrawDestroyWindow((&dv->regs)[mi->mid-MID_Registers]);
881 : debug_wins &= ~wcreat[mi->mid-MID_Registers].flag;
882 : }
883 : SavePrefs(true);
884 : }
885 :
886 : static GMenuItem popupwindowlist[] = {
887 : { { (unichar_t *) N_("Registers"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Registers },
888 : { { (unichar_t *) N_("Stack"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Stack },
889 : { { (unichar_t *) N_("Storage"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Storage },
890 : { { (unichar_t *) N_("Points"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Points },
891 : { { (unichar_t *) N_("Cvt"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Cvt },
892 : { { (unichar_t *) N_("Raster"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Raster },
893 : { { (unichar_t *) N_("Gloss"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Gloss },
894 : GMENUITEM_EMPTY
895 : };
896 :
897 : static int DV_WindowMenu(GGadget *g, GEvent *e) {
898 : DebugView *dv;
899 : GEvent fake;
900 : GRect pos;
901 : static int done = false;
902 :
903 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonpress ) {
904 : dv = GDrawGetUserData(GGadgetGetWindow(g));
905 : if ( !done ) {
906 : int i;
907 : for ( i=0; popupwindowlist[i].ti.text!=NULL; ++i )
908 : popupwindowlist[i].ti.text = (unichar_t *) _((char *) popupwindowlist[i].ti.text);
909 : done = true;
910 : }
911 : popupwindowlist[0].ti.checked = dv->regs!=NULL;
912 : popupwindowlist[1].ti.checked = dv->stack!=NULL;
913 : popupwindowlist[2].ti.checked = dv->storage!=NULL;
914 : popupwindowlist[3].ti.checked = dv->points!=NULL;
915 : popupwindowlist[4].ti.checked = dv->cvt!=NULL;
916 : popupwindowlist[5].ti.checked = dv->raster!=NULL;
917 : popupwindowlist[6].ti.checked = dv->gloss!=NULL;
918 : GGadgetGetSize(g,&pos);
919 : memset(&fake,0,sizeof(fake));
920 : fake.type = et_mousedown;
921 : fake.w = dv->dv;
922 : fake.u.mouse.x = pos.x;
923 : fake.u.mouse.y = pos.y+pos.height;
924 : GMenuCreatePopupMenu(dv->dv,&fake, popupwindowlist);
925 : }
926 : return( true );
927 : }
928 :
929 : static int DV_Exit(GGadget *g, GEvent *e) {
930 : DebugView *dv;
931 :
932 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
933 : dv = GDrawGetUserData(GGadgetGetWindow(g));
934 : CVDebugFree(dv);
935 : }
936 : return( true );
937 : }
938 :
939 : static void DVExpose(GWindow pixmap, DebugView *dv,GEvent *event) {
940 : GDrawSetLineWidth(pixmap,0);
941 : GDrawDrawLine(pixmap, 0, dv->toph-1, dv->dwidth, dv->toph-1, 0x000000 );
942 : }
943 :
944 : int DVChar(DebugView *dv, GEvent *event) {
945 :
946 : if ( event->u.chr.state&(ksm_control|ksm_meta) || dv==NULL )
947 : return( false );
948 : /* Can't redo F1, handled by menu */
949 : if ( event->u.chr.keysym == GK_Help )
950 : return( false );
951 : if ( event->u.chr.keysym >= GK_F1 && event->u.chr.keysym<=GK_F10 )
952 : return( false );
953 :
954 : switch ( event->u.chr.keysym ) {
955 : case 's': case 'S': /* Step */
956 : DVGoFigure(dv,dgt_step);
957 : break;
958 : case 'n': case 'N': /* Next */
959 : DVGoFigure(dv,dgt_next);
960 : break;
961 : case 'f': case 'F': /* finish */
962 : DVGoFigure(dv,dgt_stepout);
963 : break;
964 : case 'c': case 'C': /* Continue */
965 : DVGoFigure(dv,dgt_continue);
966 : break;
967 : case 'k': case 'K': case 'q': case 'Q': /* Kill (debugger) */
968 : CVDebugFree(dv);
969 : break;
970 : case 'r': case 'R': /* run/restart (debugger) */
971 : CVDebugReInit(dv->cv,true,DebuggingFpgm(dv->dc));
972 : break;
973 : default:
974 : /* The window check is to prevent infinite loops since CVChar can */
975 : /* call DVChar too */
976 : if ( event->w == dv->dv || event->w == dv->v ) {
977 : CVChar(dv->cv,event);
978 : return( true );
979 : }
980 :
981 : return( false );
982 : }
983 : return( true );
984 : }
985 :
986 : static int DV_HandleChar(struct instrinfo *ii, GEvent *event) {
987 : DebugView *dv = (ii->userdata);
988 : return( DVChar(dv,event));
989 : }
990 :
991 : static int dvraster_e_h(GWindow gw, GEvent *event) {
992 : DebugView *dv = (DebugView *) GDrawGetUserData(gw);
993 :
994 : if ( dv==NULL )
995 : return( true );
996 :
997 : switch ( event->type ) {
998 : case et_expose:
999 : DVRasterExpose(gw,dv,event);
1000 : break;
1001 : case et_char:
1002 : return( DVChar(dv,event));
1003 : break;
1004 : case et_close:
1005 : GDrawDestroyWindow(dv->raster);
1006 : debug_wins &= ~dw_raster;
1007 : break;
1008 : case et_destroy:
1009 : dv->raster = NULL;
1010 : break;
1011 : case et_mouseup: case et_mousedown:
1012 : case et_mousemove:
1013 : GGadgetEndPopup();
1014 : break;
1015 : default:
1016 : /* */
1017 : break;
1018 : }
1019 : return( true );
1020 : }
1021 :
1022 : static const int reg_size = 26;
1023 :
1024 : static void DVReg_SetScrollBar(DebugView *dv) {
1025 : GRect size;
1026 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
1027 : int lh = exc==NULL ? 0 : reg_size;
1028 :
1029 : GDrawGetSize(dv->regs,&size);
1030 : GScrollBarSetBounds(dv->regsb,0,lh,size.height/dv->ii.fh);
1031 : if ( dv->reg_offtop + size.height/dv->ii.fh > lh ) {
1032 : int lpos = lh-size.height/dv->ii.fh;
1033 : if ( lpos<0 ) lpos = 0;
1034 : dv->reg_offtop = lpos;
1035 : }
1036 : GScrollBarSetPos(dv->regsb,dv->reg_offtop);
1037 : }
1038 :
1039 : static void dvreg_scroll(DebugView *dv,struct sbevent *sb) {
1040 : int newpos = dv->reg_offtop;
1041 : GRect size;
1042 : extern int _GScrollBar_Width;
1043 :
1044 : GDrawGetSize(dv->regs,&size);
1045 : switch( sb->type ) {
1046 : case et_sb_top:
1047 : newpos = 0;
1048 : break;
1049 : case et_sb_uppage:
1050 : newpos -= size.height/dv->ii.fh;
1051 : break;
1052 : case et_sb_up:
1053 : --newpos;
1054 : break;
1055 : case et_sb_down:
1056 : ++newpos;
1057 : break;
1058 : case et_sb_downpage:
1059 : newpos += size.height/dv->ii.fh;
1060 : break;
1061 : case et_sb_bottom:
1062 : newpos = reg_size-size.height/dv->ii.fh;
1063 : break;
1064 : case et_sb_thumb:
1065 : case et_sb_thumbrelease:
1066 : newpos = sb->pos;
1067 : break;
1068 : }
1069 : if ( newpos>reg_size-size.height/dv->ii.fh )
1070 : newpos = reg_size-size.height/dv->ii.fh;
1071 : if ( newpos<0 ) newpos =0;
1072 : if ( newpos!=dv->reg_offtop ) {
1073 : int diff = newpos-dv->reg_offtop;
1074 : dv->reg_offtop = newpos;
1075 : GScrollBarSetPos(dv->regsb,dv->reg_offtop);
1076 : size.x = size.y = 0;
1077 : size.width -= GDrawPointsToPixels(dv->gloss,_GScrollBar_Width);
1078 : GDrawScroll(dv->regs,&size,0,diff*dv->ii.fh);
1079 : }
1080 : }
1081 :
1082 : static int dvreg_e_h(GWindow gw, GEvent *event) {
1083 : DebugView *dv = (DebugView *) GDrawGetUserData(gw);
1084 : GRect r,g;
1085 :
1086 : if ( dv==NULL )
1087 : return( true );
1088 :
1089 : switch ( event->type ) {
1090 : case et_expose:
1091 : DVRegExpose(gw,dv,event);
1092 : break;
1093 : case et_char:
1094 : return( DVChar(dv,event));
1095 : break;
1096 : case et_controlevent:
1097 : switch ( event->u.control.subtype ) {
1098 : case et_scrollbarchange:
1099 : dvreg_scroll(dv,&event->u.control.u.sb);
1100 : break;
1101 : }
1102 : break;
1103 : case et_resize:
1104 : GDrawGetSize(gw,&r);
1105 : GGadgetGetSize(dv->regsb,&g);
1106 : GGadgetMove(dv->regsb,r.width-g.width,0);
1107 : GGadgetResize(dv->regsb,g.width,r.height);
1108 : DVReg_SetScrollBar(dv);
1109 : GDrawRequestExpose(dv->regs,NULL,false);
1110 : break;
1111 : case et_close:
1112 : GDrawDestroyWindow(dv->regs);
1113 : debug_wins &= ~dw_registers;
1114 : break;
1115 : case et_destroy:
1116 : dv->regs = NULL;
1117 : break;
1118 : case et_mouseup: case et_mousedown:
1119 : case et_mousemove:
1120 : GGadgetEndPopup();
1121 : break;
1122 : }
1123 : return( true );
1124 : }
1125 :
1126 : static void DVStack_SetScrollBar(DebugView *dv) {
1127 : GRect size;
1128 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
1129 : int lh = exc==NULL ? 0 : exc->top;
1130 :
1131 : GDrawGetSize(dv->stack,&size);
1132 : GScrollBarSetBounds(dv->stacksb,0,lh,size.height/dv->ii.fh);
1133 : if ( dv->stack_offtop + size.height/dv->ii.fh > lh ) {
1134 : int lpos = lh-size.height/dv->ii.fh;
1135 : if ( lpos<0 ) lpos = 0;
1136 : dv->stack_offtop = lpos;
1137 : }
1138 : GScrollBarSetPos(dv->stacksb,dv->stack_offtop);
1139 : }
1140 :
1141 : static void dvstack_scroll(DebugView *dv,struct sbevent *sb) {
1142 : int newpos = dv->stack_offtop;
1143 : GRect size;
1144 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
1145 : extern int _GScrollBar_Width;
1146 :
1147 : GDrawGetSize(dv->stack,&size);
1148 : switch( sb->type ) {
1149 : case et_sb_top:
1150 : newpos = 0;
1151 : break;
1152 : case et_sb_uppage:
1153 : newpos -= size.height/dv->ii.fh;
1154 : break;
1155 : case et_sb_up:
1156 : --newpos;
1157 : break;
1158 : case et_sb_down:
1159 : ++newpos;
1160 : break;
1161 : case et_sb_downpage:
1162 : newpos += size.height/dv->ii.fh;
1163 : break;
1164 : case et_sb_bottom:
1165 : newpos = exc->top-size.height/dv->ii.fh;
1166 : break;
1167 : case et_sb_thumb:
1168 : case et_sb_thumbrelease:
1169 : newpos = sb->pos;
1170 : break;
1171 : }
1172 : if ( newpos>exc->top-size.height/dv->ii.fh )
1173 : newpos = exc->top-size.height/dv->ii.fh;
1174 : if ( newpos<0 ) newpos =0;
1175 : if ( newpos!=dv->stack_offtop ) {
1176 : int diff = newpos-dv->stack_offtop;
1177 : dv->stack_offtop = newpos;
1178 : GScrollBarSetPos(dv->stacksb,dv->stack_offtop);
1179 : size.x = size.y = 0;
1180 : size.width -= GDrawPointsToPixels(dv->gloss,_GScrollBar_Width);
1181 : GDrawScroll(dv->stack,&size,0,diff*dv->ii.fh);
1182 : }
1183 : }
1184 :
1185 : static int dvstack_e_h(GWindow gw, GEvent *event) {
1186 : DebugView *dv = (DebugView *) GDrawGetUserData(gw);
1187 : GRect r,g;
1188 :
1189 : if ( dv==NULL )
1190 : return( true );
1191 :
1192 : switch ( event->type ) {
1193 : case et_expose:
1194 : DVStackExpose(gw,dv,event);
1195 : break;
1196 : case et_char:
1197 : return( DVChar(dv,event));
1198 : break;
1199 : case et_controlevent:
1200 : switch ( event->u.control.subtype ) {
1201 : case et_scrollbarchange:
1202 : dvstack_scroll(dv,&event->u.control.u.sb);
1203 : break;
1204 : }
1205 : break;
1206 : case et_resize:
1207 : GDrawGetSize(gw,&r);
1208 : GGadgetGetSize(dv->stacksb,&g);
1209 : GGadgetMove(dv->stacksb,r.width-g.width,0);
1210 : GGadgetResize(dv->stacksb,g.width,r.height);
1211 : DVStack_SetScrollBar(dv);
1212 : GDrawRequestExpose(dv->stack,NULL,false);
1213 : break;
1214 : case et_close:
1215 : GDrawDestroyWindow(dv->stack);
1216 : debug_wins &= ~dw_stack;
1217 : break;
1218 : case et_destroy:
1219 : dv->stack = NULL;
1220 : break;
1221 : case et_mouseup: case et_mousedown:
1222 : case et_mousemove:
1223 : GGadgetEndPopup();
1224 : break;
1225 : }
1226 : return( true );
1227 : }
1228 :
1229 : static void DVStorage_SetScrollBar(DebugView *dv) {
1230 : GRect size;
1231 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
1232 : int lh = exc==NULL ? 0 : exc->storeSize;
1233 :
1234 : GDrawGetSize(dv->storage,&size);
1235 : GScrollBarSetBounds(dv->storagesb,0,lh,size.height/dv->ii.fh);
1236 : if ( dv->storage_offtop + size.height/dv->ii.fh > lh ) {
1237 : int lpos = lh-size.height/dv->ii.fh;
1238 : if ( lpos<0 ) lpos = 0;
1239 : dv->storage_offtop = lpos;
1240 : }
1241 : GScrollBarSetPos(dv->storagesb,dv->storage_offtop);
1242 : }
1243 :
1244 : static void dvstorage_scroll(DebugView *dv,struct sbevent *sb) {
1245 : int newpos = dv->storage_offtop;
1246 : GRect size;
1247 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
1248 : extern int _GScrollBar_Width;
1249 :
1250 : GDrawGetSize(dv->storage,&size);
1251 : switch( sb->type ) {
1252 : case et_sb_top:
1253 : newpos = 0;
1254 : break;
1255 : case et_sb_uppage:
1256 : newpos -= size.height/dv->ii.fh;
1257 : break;
1258 : case et_sb_up:
1259 : --newpos;
1260 : break;
1261 : case et_sb_down:
1262 : ++newpos;
1263 : break;
1264 : case et_sb_downpage:
1265 : newpos += size.height/dv->ii.fh;
1266 : break;
1267 : case et_sb_bottom:
1268 : newpos = exc->storeSize-size.height/dv->ii.fh;
1269 : break;
1270 : case et_sb_thumb:
1271 : case et_sb_thumbrelease:
1272 : newpos = sb->pos;
1273 : break;
1274 : }
1275 : if ( newpos>exc->storeSize-size.height/dv->ii.fh )
1276 : newpos = exc->storeSize-size.height/dv->ii.fh;
1277 : if ( newpos<0 ) newpos =0;
1278 : if ( newpos!=dv->storage_offtop ) {
1279 : int diff = newpos-dv->storage_offtop;
1280 : dv->storage_offtop = newpos;
1281 : GScrollBarSetPos(dv->storagesb,dv->storage_offtop);
1282 : size.x = size.y = 0;
1283 : size.width -= GDrawPointsToPixels(dv->gloss,_GScrollBar_Width);
1284 : GDrawScroll(dv->storage,&size,0,diff*dv->ii.fh);
1285 : }
1286 : }
1287 :
1288 : static int dvstore_e_h(GWindow gw, GEvent *event) {
1289 : DebugView *dv = (DebugView *) GDrawGetUserData(gw);
1290 : GRect r,g;
1291 :
1292 : if ( dv==NULL )
1293 : return( true );
1294 :
1295 : switch ( event->type ) {
1296 : case et_expose:
1297 : DVStorageExpose(gw,dv,event);
1298 : break;
1299 : case et_char:
1300 : return( DVChar(dv,event));
1301 : break;
1302 : case et_controlevent:
1303 : switch ( event->u.control.subtype ) {
1304 : case et_scrollbarchange:
1305 : dvstorage_scroll(dv,&event->u.control.u.sb);
1306 : break;
1307 : }
1308 : break;
1309 : case et_resize:
1310 : GDrawGetSize(gw,&r);
1311 : GGadgetGetSize(dv->storagesb,&g);
1312 : GGadgetMove(dv->storagesb,r.width-g.width,0);
1313 : GGadgetResize(dv->storagesb,g.width,r.height);
1314 : DVStorage_SetScrollBar(dv);
1315 : GDrawRequestExpose(gw,NULL,false);
1316 : break;
1317 : case et_close:
1318 : GDrawDestroyWindow(dv->storage);
1319 : debug_wins &= ~dw_storage;
1320 : break;
1321 : case et_destroy:
1322 : dv->storage = NULL;
1323 : break;
1324 : case et_mouseup: {
1325 : int i;
1326 : int n;
1327 : uint8 *watches;
1328 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
1329 : i = (event->u.mouse.y-3)/dv->ii.fh+dv->storage_offtop;
1330 : if ( i>=0 && exc!=NULL ) {
1331 : watches = DebuggerGetWatchStores(dv->dc,&n);
1332 : if ( watches==NULL ) {
1333 : watches = calloc(n,sizeof(uint8));
1334 : DebuggerSetWatchStores(dv->dc,n,watches);
1335 : }
1336 : if ( i<n ) {
1337 : watches[i] = !watches[i];
1338 : GDrawRequestExpose(dv->storage,NULL,false);
1339 : }
1340 : }
1341 : } /* Fall through */;
1342 : case et_mousedown:
1343 : case et_mousemove:
1344 : GGadgetEndPopup();
1345 : break;
1346 : }
1347 : return( true );
1348 : }
1349 :
1350 : static int dvpts_cnt(DebugView *dv) {
1351 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
1352 : int i, l, cnt;
1353 : FT_Vector *pts;
1354 : int n;
1355 : TT_GlyphZoneRec *r;
1356 :
1357 : if ( exc==NULL ) /* Can happen in glyphs with no instructions */
1358 : return( 0 );
1359 :
1360 : show_twilight = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Twilight));
1361 : show_current = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Current));
1362 : r = show_twilight ? &exc->twilight : &exc->pts;
1363 : n = r->n_points;
1364 : pts = show_current ? r->cur : r->org;
1365 :
1366 : cnt = 0;
1367 : for ( i=0; i<n; ++i ) {
1368 : if ( i==0 ) l=n-5; else l=i-1;
1369 : if ( !show_twilight && i<n-4 &&
1370 : !(r->tags[i]&FT_Curve_Tag_On) && !(r->tags[l]&FT_Curve_Tag_On))
1371 : ++cnt;
1372 : ++cnt;
1373 : }
1374 : return( cnt );
1375 : }
1376 :
1377 : static void DVPointsFigureSB(DebugView *dv) {
1378 : int l, cnt;
1379 : GRect size;
1380 :
1381 : cnt = dvpts_cnt(dv);
1382 : GDrawGetSize(dv->points_v,&size);
1383 : l = size.height/dv->ii.fh;
1384 : GScrollBarSetBounds(dv->pts_vsb,0,cnt,l);
1385 : if ( dv->points_offtop+l > cnt )
1386 : dv->points_offtop = cnt-l;
1387 : if ( dv->points_offtop < 0 )
1388 : dv->points_offtop = 0;
1389 : GScrollBarSetPos(dv->pts_vsb,dv->points_offtop);
1390 : }
1391 :
1392 : static int dvpointsv_e_h(GWindow gw, GEvent *event) {
1393 : DebugView *dv = (DebugView *) GDrawGetUserData(gw);
1394 :
1395 : if ( dv==NULL )
1396 : return( true );
1397 :
1398 : switch ( event->type ) {
1399 : case et_expose:
1400 : DVPointsVExpose(gw,dv,event);
1401 : break;
1402 : case et_char:
1403 : return( DVChar(dv,event));
1404 : break;
1405 : case et_mouseup: {
1406 : int i,j,k,l,ph;
1407 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
1408 : i = (event->u.mouse.y-3)/dv->ii.fh+dv->points_offtop;
1409 : if ( i>=0 && exc!=NULL && !GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Twilight)) ) {
1410 : ph = FreeTypeAtLeast(2,1,8)?4:2; /* number of phantom pts */
1411 : for ( j=k=0; j<exc->pts.n_points; ++j ) {
1412 : l = (j==0) ? exc->pts.n_points-ph : j-1;
1413 : if ( !(exc->pts.tags[j]&FT_Curve_Tag_On) && !(exc->pts.tags[l]&FT_Curve_Tag_On)) {
1414 : if ( k==i )
1415 : break;
1416 : ++k;
1417 : }
1418 : if ( k==i ) {
1419 : int n;
1420 : uint8 *watches;
1421 : watches = DebuggerGetWatches(dv->dc,&n);
1422 : if ( watches==NULL ) {
1423 : watches = calloc(n,sizeof(uint8));
1424 : DebuggerSetWatches(dv->dc,n,watches);
1425 : }
1426 : if ( j<n ) {
1427 : SplineSet *ss;
1428 : SplinePoint *sp;
1429 : watches[j] = !watches[j];
1430 : for ( ss=dv->cv->b.layerheads[dv->cv->b.drawmode]->splines; ss!=NULL; ss=ss->next ) {
1431 : for ( sp=ss->first; sp->ttfindex<=j || sp->ttfindex==0xffff; ) {
1432 : if ( sp->ttfindex==j )
1433 : sp->watched = watches[j];
1434 : if ( sp->next==NULL )
1435 : break;
1436 : sp = sp->next->to;
1437 : if ( sp==ss->first )
1438 : break;
1439 : }
1440 : }
1441 : }
1442 : GDrawRequestExpose(dv->points_v,NULL,false);
1443 : GDrawRequestExpose(dv->cv->v,NULL,false);
1444 : break;
1445 : }
1446 : ++k;
1447 : }
1448 : }
1449 : } /* Fall through */;
1450 : case et_mousedown:
1451 : case et_mousemove:
1452 : GGadgetEndPopup();
1453 : break;
1454 : case et_resize:
1455 : DVPointsFigureSB(dv);
1456 : break;
1457 : }
1458 : return( true );
1459 : }
1460 :
1461 : static void dvpts_scroll(DebugView *dv,struct sbevent *sb) {
1462 : int newpos = dv->points_offtop;
1463 : GRect size;
1464 : int cnt;
1465 :
1466 : GDrawGetSize(dv->points_v,&size);
1467 : cnt = dvpts_cnt(dv);
1468 : switch( sb->type ) {
1469 : case et_sb_top:
1470 : newpos = 0;
1471 : break;
1472 : case et_sb_uppage:
1473 : newpos -= size.height/dv->ii.fh;
1474 : break;
1475 : case et_sb_up:
1476 : --newpos;
1477 : break;
1478 : case et_sb_down:
1479 : ++newpos;
1480 : break;
1481 : case et_sb_downpage:
1482 : newpos += size.height/dv->ii.fh;
1483 : break;
1484 : case et_sb_bottom:
1485 : newpos = cnt-size.height/dv->ii.fh;
1486 : break;
1487 : case et_sb_thumb:
1488 : case et_sb_thumbrelease:
1489 : newpos = sb->pos;
1490 : break;
1491 : }
1492 : if ( newpos>cnt-size.height/dv->ii.fh )
1493 : newpos = cnt-size.height/dv->ii.fh;
1494 : if ( newpos<0 ) newpos =0;
1495 : if ( newpos!=dv->points_offtop ) {
1496 : int diff = newpos-dv->points_offtop;
1497 : dv->points_offtop = newpos;
1498 : GScrollBarSetPos(dv->pts_vsb,dv->points_offtop);
1499 : GDrawScroll(dv->points_v,NULL,0,diff*dv->ii.fh);
1500 : }
1501 : }
1502 :
1503 : static int dvpoints_e_h(GWindow gw, GEvent *event) {
1504 : DebugView *dv = (DebugView *) GDrawGetUserData(gw);
1505 : GRect r;
1506 : extern int _GScrollBar_Width;
1507 : int sbwidth;
1508 :
1509 : if ( dv==NULL )
1510 : return( true );
1511 :
1512 : switch ( event->type ) {
1513 : case et_expose:
1514 : DVPointsExpose(gw,dv,event);
1515 : break;
1516 : case et_char:
1517 : return( DVChar(dv,event));
1518 : break;
1519 : case et_controlevent:
1520 : switch ( event->u.control.subtype ) {
1521 : case et_radiochanged:
1522 : GDrawRequestExpose(dv->points_v,NULL,false);
1523 : DVPointsFigureSB(dv);
1524 : break;
1525 : case et_scrollbarchange:
1526 : dvpts_scroll(dv,&event->u.control.u.sb);
1527 : break;
1528 : }
1529 : break;
1530 : case et_resize:
1531 : GDrawGetSize(gw,&r);
1532 : sbwidth = GDrawPointsToPixels(gw,_GScrollBar_Width);
1533 : GDrawResize(dv->points_v,r.width-sbwidth,r.height-dv->pts_head);
1534 : GGadgetResize(dv->pts_vsb,sbwidth,r.height-dv->pts_head);
1535 : GGadgetMove(dv->pts_vsb,r.width-sbwidth,dv->pts_head);
1536 : break;
1537 : case et_close:
1538 : GDrawDestroyWindow(dv->points);
1539 : debug_wins &= ~dw_points;
1540 : break;
1541 : case et_destroy:
1542 : dv->points = NULL;
1543 : dv->points_v = NULL;
1544 : break;
1545 : case et_mouseup: case et_mousedown:
1546 : case et_mousemove:
1547 : GGadgetEndPopup();
1548 : break;
1549 : }
1550 : return( true );
1551 : }
1552 :
1553 : static void DVCvt_SetScrollBar(DebugView *dv) {
1554 : GRect size;
1555 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
1556 : int lh = exc==NULL ? 0 : exc->cvtSize;
1557 :
1558 : GDrawGetSize(dv->cvt,&size);
1559 : GScrollBarSetBounds(dv->cvtsb,0,lh,size.height/dv->ii.fh);
1560 : if ( dv->cvt_offtop + size.height/dv->ii.fh > lh ) {
1561 : int lpos = lh-size.height/dv->ii.fh;
1562 : if ( lpos<0 ) lpos = 0;
1563 : dv->cvt_offtop = lpos;
1564 : }
1565 : GScrollBarSetPos(dv->cvtsb,dv->cvt_offtop);
1566 : }
1567 :
1568 :
1569 : static void dvcvt_scroll(DebugView *dv,struct sbevent *sb) {
1570 : int newpos = dv->cvt_offtop;
1571 : GRect size;
1572 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
1573 : extern int _GScrollBar_Width;
1574 :
1575 : GDrawGetSize(dv->cvt,&size);
1576 : switch( sb->type ) {
1577 : case et_sb_top:
1578 : newpos = 0;
1579 : break;
1580 : case et_sb_uppage:
1581 : newpos -= size.height/dv->ii.fh;
1582 : break;
1583 : case et_sb_up:
1584 : --newpos;
1585 : break;
1586 : case et_sb_down:
1587 : ++newpos;
1588 : break;
1589 : case et_sb_downpage:
1590 : newpos += size.height/dv->ii.fh;
1591 : break;
1592 : case et_sb_bottom:
1593 : newpos = exc->cvtSize-size.height/dv->ii.fh;
1594 : break;
1595 : case et_sb_thumb:
1596 : case et_sb_thumbrelease:
1597 : newpos = sb->pos;
1598 : break;
1599 : }
1600 : if ( newpos>exc->cvtSize-size.height/dv->ii.fh )
1601 : newpos = exc->cvtSize-size.height/dv->ii.fh;
1602 : if ( newpos<0 ) newpos =0;
1603 : if ( newpos!=dv->cvt_offtop ) {
1604 : int diff = newpos-dv->cvt_offtop;
1605 : dv->cvt_offtop = newpos;
1606 : GScrollBarSetPos(dv->cvtsb,dv->cvt_offtop);
1607 : size.x = size.y = 0;
1608 : size.width -= GDrawPointsToPixels(dv->gloss,_GScrollBar_Width);
1609 : GDrawScroll(dv->cvt,&size,0,diff*dv->ii.fh);
1610 : }
1611 : }
1612 :
1613 : static int dvcvt_e_h(GWindow gw, GEvent *event) {
1614 : DebugView *dv = (DebugView *) GDrawGetUserData(gw);
1615 : GRect r,g;
1616 :
1617 : if ( dv==NULL )
1618 : return( true );
1619 :
1620 : switch ( event->type ) {
1621 : case et_expose:
1622 : DVCvtExpose(gw,dv,event);
1623 : break;
1624 : case et_char:
1625 : return( DVChar(dv,event));
1626 : break;
1627 : case et_controlevent:
1628 : switch ( event->u.control.subtype ) {
1629 : case et_scrollbarchange:
1630 : dvcvt_scroll(dv,&event->u.control.u.sb);
1631 : break;
1632 : }
1633 : break;
1634 : case et_resize:
1635 : GDrawGetSize(gw,&r);
1636 : GGadgetGetSize(dv->cvtsb,&g);
1637 : GGadgetMove(dv->cvtsb,r.width-g.width,0);
1638 : GGadgetResize(dv->cvtsb,g.width,r.height);
1639 : DVCvt_SetScrollBar(dv);
1640 : GDrawRequestExpose(dv->cvt,NULL,false);
1641 : break;
1642 : case et_close:
1643 : GDrawDestroyWindow(dv->cvt);
1644 : debug_wins &= ~dw_cvt;
1645 : break;
1646 : case et_destroy:
1647 : dv->cvt = NULL;
1648 : break;
1649 : case et_mouseup: {
1650 : int i;
1651 : int n;
1652 : uint8 *watches;
1653 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
1654 : i = (event->u.mouse.y-3)/dv->ii.fh+dv->cvt_offtop;
1655 : if ( i>=0 && exc!=NULL ) {
1656 : watches = DebuggerGetWatchCvts(dv->dc,&n);
1657 : if ( watches==NULL ) {
1658 : watches = calloc(n,sizeof(uint8));
1659 : DebuggerSetWatchCvts(dv->dc,n,watches);
1660 : }
1661 : if ( i<n ) {
1662 : watches[i] = !watches[i];
1663 : GDrawRequestExpose(dv->cvt,NULL,false);
1664 : }
1665 : }
1666 : } /* Fall through */;
1667 : case et_mousedown:
1668 : case et_mousemove:
1669 : GGadgetEndPopup();
1670 : break;
1671 : }
1672 : return( true );
1673 : }
1674 :
1675 : int CVXPos(DebugView *dv,int offset,int width) {
1676 : GRect r, screensize;
1677 : int x;
1678 :
1679 : GDrawGetSize(dv->cv->gw,&r);
1680 : GDrawGetSize(GDrawGetRoot(NULL),&screensize);
1681 : x = r.x+r.width+10 + offset;
1682 : if ( x+width >screensize.width )
1683 : x = screensize.width - width;
1684 : return( x );
1685 : }
1686 :
1687 : static void DVCreateRaster(DebugView *dv) {
1688 : GWindowAttrs wattrs;
1689 : GRect pos;
1690 :
1691 : memset(&wattrs,0,sizeof(wattrs));
1692 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
1693 : wattrs.event_masks = -1;
1694 : wattrs.cursor = ct_mypointer;
1695 : wattrs.utf8_window_title = _("Current Raster (TrueType)");
1696 : pos.width = 50; pos.height = 50;
1697 : pos.x = CVXPos(dv,143,pos.width); pos.y = 1;
1698 : dv->raster = GDrawCreateTopWindow(NULL,&pos,dvraster_e_h,dv,&wattrs);
1699 : GDrawSetVisible(dv->raster,true);
1700 : }
1701 :
1702 : static void DVCreateRegs(DebugView *dv) {
1703 : GWindowAttrs wattrs;
1704 : GRect pos;
1705 : GGadgetData gd;
1706 : extern int _GScrollBar_Width;
1707 :
1708 : memset(&wattrs,0,sizeof(wattrs));
1709 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
1710 : wattrs.event_masks = -1;
1711 : wattrs.cursor = ct_mypointer;
1712 : wattrs.utf8_window_title = _("Registers (TrueType)");
1713 : pos.width = 143; pos.height = 269;
1714 : pos.x = CVXPos(dv,0,pos.width); pos.y = 1;
1715 : dv->regs = GDrawCreateTopWindow(NULL,&pos,dvreg_e_h,dv,&wattrs);
1716 :
1717 : memset(&gd,0,sizeof(gd));
1718 :
1719 : gd.pos.y = 0; gd.pos.height = pos.height;
1720 : gd.pos.width = GDrawPointsToPixels(dv->regs,_GScrollBar_Width);
1721 : gd.pos.x = pos.width-gd.pos.width;
1722 : gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
1723 : dv->regsb = GScrollBarCreate(dv->regs,&gd,dv);
1724 :
1725 : GDrawSetVisible(dv->regs,true);
1726 : }
1727 :
1728 : static void DVCreateStack(DebugView *dv) {
1729 : GWindowAttrs wattrs;
1730 : GRect pos;
1731 : GGadgetData gd;
1732 : extern int _GScrollBar_Width;
1733 :
1734 : memset(&wattrs,0,sizeof(wattrs));
1735 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
1736 : wattrs.event_masks = -1;
1737 : wattrs.cursor = ct_mypointer;
1738 : wattrs.utf8_window_title = _("Stack (TrueType)");
1739 : pos.width = 143; pos.height = 269;
1740 : pos.x = CVXPos(dv,0,pos.width); pos.y = 302;
1741 : dv->stack = GDrawCreateTopWindow(NULL,&pos,dvstack_e_h,dv,&wattrs);
1742 :
1743 : memset(&gd,0,sizeof(gd));
1744 :
1745 : gd.pos.y = 0; gd.pos.height = pos.height;
1746 : gd.pos.width = GDrawPointsToPixels(dv->stack,_GScrollBar_Width);
1747 : gd.pos.x = pos.width-gd.pos.width;
1748 : gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
1749 : dv->stacksb = GScrollBarCreate(dv->stack,&gd,dv);
1750 :
1751 : GDrawSetVisible(dv->stack,true);
1752 : }
1753 :
1754 : static void DVCreateStore(DebugView *dv) {
1755 : GWindowAttrs wattrs;
1756 : GRect pos;
1757 : GGadgetData gd;
1758 : extern int _GScrollBar_Width;
1759 :
1760 : memset(&wattrs,0,sizeof(wattrs));
1761 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
1762 : wattrs.event_masks = -1;
1763 : wattrs.cursor = ct_mypointer;
1764 : wattrs.utf8_window_title = _("Storage (TrueType)");
1765 : pos.width = 183; pos.height = 100;
1766 : pos.x = CVXPos(dv,0,pos.width); pos.y = 602;
1767 : dv->storage = GDrawCreateTopWindow(NULL,&pos,dvstore_e_h,dv,&wattrs);
1768 :
1769 : memset(&gd,0,sizeof(gd));
1770 :
1771 : gd.pos.y = 0; gd.pos.height = pos.height;
1772 : gd.pos.width = GDrawPointsToPixels(dv->storage,_GScrollBar_Width);
1773 : gd.pos.x = pos.width-gd.pos.width;
1774 : gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
1775 : dv->storagesb = GScrollBarCreate(dv->storage,&gd,dv);
1776 :
1777 : GDrawSetVisible(dv->storage,true);
1778 : }
1779 :
1780 : #if defined(FONTFORGE_CONFIG_SHOW_RAW_POINTS)
1781 : static int DV_Raw(GGadget *g, GEvent *e) {
1782 :
1783 : if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
1784 : GWindow ew = GGadgetGetWindow(g);
1785 : int on = GGadgetIsChecked(g);
1786 : GGadget *trans = GWidgetGetControl(ew,CID_Transform);
1787 : GGadgetSetEnabled(trans,!on);
1788 : GGadgetSetChecked(trans, on? false : show_transformed );
1789 : }
1790 : return( true );
1791 : }
1792 : #endif
1793 :
1794 : static void DVCreatePoints(DebugView *dv) {
1795 : GWindowAttrs wattrs;
1796 : GRect pos;
1797 : /*extern int _GScrollBar_Width;*/
1798 : GGadgetCreateData gcd[10];
1799 : GTextInfo label[9];
1800 : extern int _GScrollBar_Width;
1801 : int k;
1802 :
1803 : memset(&wattrs,0,sizeof(wattrs));
1804 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
1805 : wattrs.event_masks = -1;
1806 : wattrs.cursor = ct_mypointer;
1807 : wattrs.utf8_window_title = _("Points (TrueType)");
1808 : pos.width = GGadgetScale(GDrawPointsToPixels(NULL,129+_GScrollBar_Width)+19);
1809 : pos.height = 269;
1810 : pos.x = CVXPos(dv,0,pos.width); pos.y = 732;
1811 : dv->points = GDrawCreateTopWindow(NULL,&pos,dvpoints_e_h,dv,&wattrs);
1812 :
1813 : dv->pts_head = GDrawPointsToPixels(NULL,GGadgetScale(5+4*16+3));
1814 :
1815 : memset(&label,0,sizeof(label));
1816 : memset(&gcd,0,sizeof(gcd));
1817 :
1818 : label[0].text = (unichar_t *) _("Twilight");
1819 : label[0].text_is_1byte = true;
1820 : gcd[0].gd.label = &label[0];
1821 : gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 3;
1822 : gcd[0].gd.flags = gg_visible | gg_enabled | (show_twilight ? gg_cb_on : 0 );
1823 : gcd[0].gd.cid = CID_Twilight;
1824 : gcd[0].creator = GRadioCreate;
1825 :
1826 : label[1].text = (unichar_t *) _("Normal");
1827 : label[1].text_is_1byte = true;
1828 : gcd[1].gd.label = &label[1];
1829 : gcd[1].gd.pos.x = 60; gcd[1].gd.pos.y = gcd[0].gd.pos.y;
1830 : gcd[1].gd.flags = gg_visible | gg_enabled | (!show_twilight ? gg_cb_on : 0 );
1831 : gcd[1].gd.cid = CID_Normal;
1832 : gcd[1].creator = GRadioCreate;
1833 :
1834 : label[2].text = (unichar_t *) _("Current");
1835 : label[2].text_is_1byte = true;
1836 : gcd[2].gd.label = &label[2];
1837 : gcd[2].gd.pos.x = 5; gcd[2].gd.pos.y = gcd[0].gd.pos.y+16;
1838 : gcd[2].gd.flags = gg_visible | gg_enabled | gg_rad_startnew | (show_current ? gg_cb_on : 0 );
1839 : gcd[2].gd.cid = CID_Current;
1840 : gcd[2].creator = GRadioCreate;
1841 :
1842 : label[3].text = (unichar_t *) S_("Points|Original");
1843 : label[3].text_is_1byte = true;
1844 : gcd[3].gd.label = &label[3];
1845 : gcd[3].gd.pos.x = gcd[1].gd.pos.x; gcd[3].gd.pos.y = gcd[2].gd.pos.y;
1846 : gcd[3].gd.flags = gg_visible | gg_enabled | (!show_current ? gg_cb_on : 0 );
1847 : gcd[3].gd.cid = CID_Original;
1848 : gcd[3].creator = GRadioCreate;
1849 :
1850 : label[4].text = (unichar_t *) _("Grid");
1851 : label[4].text_is_1byte = true;
1852 : gcd[4].gd.label = &label[4];
1853 : gcd[4].gd.pos.x = 5; gcd[4].gd.pos.y = gcd[2].gd.pos.y+16;
1854 : gcd[4].gd.flags = gg_visible | gg_enabled | gg_rad_startnew | (show_grid ? gg_cb_on : 0 );
1855 : gcd[4].gd.cid = CID_Grid;
1856 : gcd[4].creator = GRadioCreate;
1857 :
1858 : k=5;
1859 :
1860 : #if defined(FONTFORGE_CONFIG_SHOW_RAW_POINTS)
1861 : label[k].text = (unichar_t *) _("Raw");
1862 : label[k].text_is_1byte = true;
1863 : gcd[k].gd.label = &label[k];
1864 : gcd[k].gd.pos.x = 43; gcd[k].gd.pos.y = gcd[4].gd.pos.y;
1865 : gcd[k].gd.flags = gg_visible | gg_enabled | (show_raw ? gg_cb_on : 0 );
1866 : gcd[k].gd.cid = CID_Raw;
1867 : gcd[k].gd.handle_controlevent = DV_Raw;
1868 : gcd[k++].creator = GRadioCreate;
1869 : #endif
1870 :
1871 : label[k].text = (unichar_t *) _("Em Units");
1872 : label[k].text_is_1byte = true;
1873 : gcd[k].gd.label = &label[k];
1874 : #if defined(FONTFORGE_CONFIG_SHOW_RAW_POINTS)
1875 : gcd[k].gd.pos.x = 82; gcd[k].gd.pos.y = gcd[4].gd.pos.y;
1876 : #else
1877 : gcd[k].gd.pos.x = gcd[1].gd.pos.x; gcd[k].gd.pos.y = gcd[4].gd.pos.y;
1878 : #endif
1879 : gcd[k].gd.flags = gg_visible | gg_enabled | (!show_current ? gg_cb_on : 0 );
1880 : gcd[k].gd.cid = CID_EmUnit;
1881 : gcd[k++].creator = GRadioCreate;
1882 :
1883 : label[k].text = (unichar_t *) _("Transformed");
1884 : label[k].text_is_1byte = true;
1885 : gcd[k].gd.label = &label[k];
1886 : gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[4].gd.pos.y+16;
1887 : gcd[k].gd.flags = gg_visible | (show_transformed ? gg_cb_on : 0 );
1888 : if ( dv->cv->b.layerheads[dv->cv->b.drawmode]->splines==NULL &&
1889 : dv->cv->b.layerheads[dv->cv->b.drawmode]->refs!=NULL )
1890 : gcd[k].gd.flags |= gg_enabled;
1891 : gcd[k].gd.cid = CID_Transform;
1892 : gcd[k++].creator = GCheckBoxCreate;
1893 :
1894 : gcd[k].gd.pos.width = GDrawPointsToPixels(NULL,_GScrollBar_Width);
1895 : gcd[k].gd.pos.height = pos.height-dv->pts_head;
1896 : gcd[k].gd.pos.x = pos.width-gcd[k].gd.pos.width; gcd[k].gd.pos.y = dv->pts_head;
1897 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_pos_in_pixels | gg_sb_vert;
1898 : gcd[k].creator = GScrollBarCreate;
1899 :
1900 : GGadgetsCreate(dv->points,gcd);
1901 : dv->pts_vsb = gcd[k].ret;
1902 :
1903 : pos.x = 0;
1904 : pos.y = dv->pts_head;
1905 : pos.height -= dv->pts_head;
1906 : pos.width -= gcd[6].gd.pos.width;
1907 : dv->points_v = GWidgetCreateSubWindow(dv->points,&pos,dvpointsv_e_h,dv,&wattrs);
1908 : GDrawSetVisible(dv->points_v,true);
1909 : GDrawSetVisible(dv->points,true);
1910 : }
1911 :
1912 : static void DVCreateCvt(DebugView *dv) {
1913 : GWindowAttrs wattrs;
1914 : GRect pos;
1915 : GGadgetData gd;
1916 : extern int _GScrollBar_Width;
1917 :
1918 : memset(&wattrs,0,sizeof(wattrs));
1919 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
1920 : wattrs.event_masks = -1;
1921 : wattrs.cursor = ct_mypointer;
1922 : wattrs.utf8_window_title = _("Cvt");
1923 : pos.x = 664; pos.y = 732;
1924 : pos.width = GGadgetScale(GDrawPointsToPixels(NULL,125))+20; pos.height = 169;
1925 : pos.x = CVXPos(dv,183,pos.width); pos.y = 602;
1926 : dv->cvt = GDrawCreateTopWindow(NULL,&pos,dvcvt_e_h,dv,&wattrs);
1927 :
1928 : memset(&gd,0,sizeof(gd));
1929 :
1930 : gd.pos.y = 0; gd.pos.height = pos.height;
1931 : gd.pos.width = GDrawPointsToPixels(dv->cvt,_GScrollBar_Width);
1932 : gd.pos.x = pos.width-gd.pos.width;
1933 : gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
1934 : dv->cvtsb = GScrollBarCreate(dv->cvt,&gd,dv);
1935 :
1936 : DVCvt_SetScrollBar(dv);
1937 :
1938 : GDrawSetVisible(dv->cvt,true);
1939 : }
1940 :
1941 : static int dv_e_h(GWindow gw, GEvent *event) {
1942 : DebugView *dv = (DebugView *) GDrawGetUserData(gw);
1943 :
1944 : switch ( event->type ) {
1945 : case et_expose:
1946 : DVExpose(gw,dv,event);
1947 : break;
1948 : case et_char:
1949 : return( DVChar(dv,event));
1950 : break;
1951 : case et_charup:
1952 : break;
1953 : case et_controlevent:
1954 : switch ( event->u.control.subtype ) {
1955 : case et_scrollbarchange:
1956 : instr_scroll(&dv->ii,&event->u.control.u.sb);
1957 : break;
1958 : }
1959 : break;
1960 : case et_resize:
1961 : if ( event->u.resize.sized ) {
1962 : /*DVResize(dv,event)*/;
1963 : }
1964 : break;
1965 : case et_destroy:
1966 : dv->dv = NULL;
1967 : if ( dv->cv!=NULL )
1968 : CVDebugFree(dv);
1969 : free(dv->id.bts);
1970 : free(dv);
1971 : break;
1972 : case et_mouseup: case et_mousedown:
1973 : GGadgetEndPopup();
1974 : break;
1975 : case et_mousemove:
1976 : break;
1977 : }
1978 : return( true );
1979 : }
1980 :
1981 : void CVDebugFree(DebugView *dv) {
1982 : if ( dv!=NULL ) {
1983 : CharView *cv = dv->cv;
1984 : SplineSet *ss;
1985 : SplinePoint *sp;
1986 : int dying = dv->dv==NULL;
1987 :
1988 : cv->show_ft_results = false;
1989 : DebuggerTerminate(dv->dc);
1990 : cv->dv = NULL;
1991 : if ( dv->points!=NULL ) {
1992 : GDrawSetUserData(dv->points,NULL);
1993 : GDrawSetUserData(dv->points_v,NULL);
1994 : GDrawDestroyWindow(dv->points);
1995 : }
1996 : if ( dv->raster!=NULL ) {
1997 : GDrawSetUserData(dv->raster,NULL);
1998 : GDrawDestroyWindow(dv->raster);
1999 : }
2000 : if ( dv->cvt!=NULL ) {
2001 : GDrawSetUserData(dv->cvt,NULL);
2002 : GDrawDestroyWindow(dv->cvt);
2003 : }
2004 : if ( dv->regs!=NULL ) {
2005 : GDrawSetUserData(dv->regs,NULL);
2006 : GDrawDestroyWindow(dv->regs);
2007 : }
2008 : if ( dv->stack!=NULL ) {
2009 : GDrawSetUserData(dv->stack,NULL);
2010 : GDrawDestroyWindow(dv->stack);
2011 : }
2012 : if ( dv->storage!=NULL ) {
2013 : GDrawSetUserData(dv->storage,NULL);
2014 : GDrawDestroyWindow(dv->storage);
2015 : }
2016 : if ( dv->gloss!=NULL ) {
2017 : GDrawSetUserData(dv->gloss,NULL);
2018 : GDrawDestroyWindow(dv->gloss);
2019 : }
2020 : if ( dv->dv!=NULL ) {
2021 : GDrawDestroyWindow(dv->dv);
2022 : CVResize(cv);
2023 : GDrawRequestExpose(cv->v,NULL,false);
2024 : }
2025 :
2026 : for ( ss = cv->b.layerheads[cv->b.drawmode]->splines; ss!=NULL; ss=ss->next ) {
2027 : for ( sp=ss->first; ; ) {
2028 : sp->watched = false;
2029 : if ( sp->next==NULL )
2030 : break;
2031 : sp = sp->next->to;
2032 : if ( sp==ss->first )
2033 : break;
2034 : }
2035 : }
2036 :
2037 : SplinePointListsFree(cv->b.gridfit); cv->b.gridfit = NULL;
2038 : FreeType_FreeRaster(cv->oldraster); cv->oldraster = NULL;
2039 : FreeType_FreeRaster(cv->raster); cv->raster = NULL;
2040 :
2041 : if ( !dying ) {
2042 : GDrawRequestExpose(cv->v,NULL,false);
2043 :
2044 : if ( cv->coderange!=cr_none ) {
2045 : cv->coderange = cr_none;
2046 : CVInfoDraw(cv,cv->gw);
2047 : }
2048 : }
2049 : DebugColInit();
2050 :
2051 : dv->cv = NULL;
2052 : }
2053 : }
2054 :
2055 : void CVDebugReInit(CharView *cv,int restart_debug,int dbg_fpgm) {
2056 : DebugView *dv = cv->dv;
2057 : GWindowAttrs wattrs;
2058 : GRect pos, size;
2059 : TT_ExecContext exc;
2060 : FontRequest rq;
2061 : int as,ds,ld;
2062 : GGadgetCreateData gcd[9];
2063 : GTextInfo label[9];
2064 : extern int _GScrollBar_Width;
2065 : double scalex, scaley;
2066 : int i;
2067 : static GFont *monofont = NULL;
2068 :
2069 : scalex = (cv->b.sc->parent->ascent+cv->b.sc->parent->descent)/(rint(cv->ft_pointsizex*cv->ft_dpi/72.0)) / (1<<6);
2070 : scaley = (cv->b.sc->parent->ascent+cv->b.sc->parent->descent)/(rint(cv->ft_pointsizey*cv->ft_dpi/72.0)) / (1<<6);
2071 : if ( restart_debug ) {
2072 : if ( cv->b.sc->instructions_out_of_date && cv->b.sc->ttf_instrs_len!=0 )
2073 : ff_post_notice(_("Instructions out of date"),
2074 : _("The points have been changed. This may mean that the truetype instructions now refer to the wrong points and they may cause unexpected results."));
2075 : }
2076 : if ( !restart_debug ) {
2077 : CVDebugFree(dv);
2078 : } else if ( dv==NULL ) {
2079 : int sbsize = GDrawPointsToPixels(cv->gw,_GScrollBar_Width);
2080 : cv->show_ft_results = false;
2081 : cv->dv = dv = calloc(1,sizeof(DebugView));
2082 : dv->dwidth = 260;
2083 : dv->scalex = scalex;
2084 : dv->scaley = scaley;
2085 : dv->cv = cv;
2086 : dv->layer = CVLayer((CharViewBase *) cv);
2087 : dv->dc = DebuggerCreate(cv->b.sc,dv->layer,cv->ft_pointsizey,cv->ft_pointsizex,cv->ft_dpi,dbg_fpgm,cv->ft_depth==1);
2088 : FreeType_FreeRaster(cv->raster); cv->raster = NULL;
2089 : if ( dv->dc==NULL ) {
2090 : free(dv);
2091 : cv->dv = NULL;
2092 : return;
2093 : }
2094 : memset(&wattrs,0,sizeof(wattrs));
2095 : wattrs.mask = wam_events|wam_cursor|wam_bordwidth|wam_bordcol;
2096 : wattrs.event_masks = -1;
2097 : wattrs.border_width = 0;
2098 : wattrs.border_color = 0x000000;
2099 : wattrs.cursor = ct_mypointer;
2100 : pos.x = 0; pos.y = 0;
2101 : pos.width = dv->dwidth; pos.height = cv->height;
2102 : dv->dv = GWidgetCreateSubWindow(cv->gw,&pos,dv_e_h,dv,&wattrs);
2103 : GDrawSetVisible(dv->dv,true);
2104 :
2105 : dv->toph = 36;
2106 : memset(&gcd,0,sizeof(gcd));
2107 : memset(&label,0,sizeof(label));
2108 : gcd[0].gd.pos.y = dv->toph; gcd[0].gd.pos.height = pos.height-dv->toph;
2109 : gcd[0].gd.pos.width = GDrawPointsToPixels(cv->gw,_GScrollBar_Width);
2110 : gcd[0].gd.pos.x = pos.width-gcd[0].gd.pos.width;
2111 : gcd[0].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
2112 : gcd[0].creator = GScrollBarCreate;
2113 :
2114 : gcd[1].gd.pos.y = 2; gcd[1].gd.pos.x = 2;
2115 : gcd[1].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
2116 : gcd[1].gd.cid = dgt_step;
2117 : gcd[1].gd.label = &label[1];
2118 : label[1].image = &GIcon_stepinto;
2119 : gcd[1].gd.handle_controlevent = DV_Run;
2120 : gcd[1].gd.popup_msg = (unichar_t *) _("Step into");
2121 : gcd[1].creator = GButtonCreate;
2122 :
2123 : gcd[2].gd.pos.y = 2; gcd[2].gd.pos.x = 38;
2124 : gcd[2].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
2125 : gcd[2].gd.cid = dgt_next;
2126 : gcd[2].gd.label = &label[2];
2127 : label[2].image = &GIcon_stepover;
2128 : gcd[2].gd.handle_controlevent = DV_Run;
2129 : gcd[2].gd.popup_msg = (unichar_t *) _("Step over (Next)");
2130 : gcd[2].creator = GButtonCreate;
2131 :
2132 : gcd[3].gd.pos.y = 2; gcd[3].gd.pos.x = 74;
2133 : gcd[3].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
2134 : gcd[3].gd.cid = dgt_stepout;
2135 : gcd[3].gd.label = &label[3];
2136 : label[3].image = &GIcon_stepout;
2137 : gcd[3].gd.handle_controlevent = DV_Run;
2138 : gcd[3].gd.popup_msg = (unichar_t *) _("Step out of current function");
2139 : gcd[3].creator = GButtonCreate;
2140 :
2141 : gcd[4].gd.pos.y = 2; gcd[4].gd.pos.x = 110;
2142 : gcd[4].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
2143 : gcd[4].gd.cid = dgt_continue;
2144 : gcd[4].gd.label = &label[4];
2145 : label[4].image = &GIcon_continue;
2146 : gcd[4].gd.handle_controlevent = DV_Run;
2147 : gcd[4].gd.popup_msg = (unichar_t *) _("Continue");
2148 : gcd[4].creator = GButtonCreate;
2149 :
2150 : gcd[5].gd.pos.y = 2; gcd[5].gd.pos.x = 146;
2151 : gcd[5].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
2152 : /*gcd[5].gd.cid = dgt_continue;*/
2153 : gcd[5].gd.label = &label[5];
2154 : label[5].image = &GIcon_watchpnt;
2155 : gcd[5].gd.handle_controlevent = DV_WatchPnt;
2156 : gcd[5].gd.popup_msg = (unichar_t *) _("Watch all selected points\n(stop when a point moves)");
2157 : gcd[5].creator = GButtonCreate;
2158 :
2159 : gcd[6].gd.pos.y = 2; gcd[6].gd.pos.x = 182;
2160 : gcd[6].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
2161 : /*gcd[6].gd.cid = dgt_continue;*/
2162 : gcd[6].gd.label = &label[6];
2163 : label[6].image = &GIcon_menudelta;
2164 : gcd[6].gd.handle_controlevent = DV_WindowMenu;
2165 : gcd[6].gd.popup_msg = (unichar_t *) _("Window");
2166 : gcd[6].creator = GButtonCreate;
2167 :
2168 : gcd[7].gd.pos.y = 2; gcd[7].gd.pos.x = 218;
2169 : gcd[7].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
2170 : /*gcd[7].gd.cid = dgt_continue;*/
2171 : gcd[7].gd.label = &label[7];
2172 : label[7].image = &GIcon_exit;
2173 : gcd[7].gd.handle_controlevent = DV_Exit;
2174 : gcd[7].gd.popup_msg = (unichar_t *) _("Exit Debugger");
2175 : gcd[7].creator = GButtonCreate;
2176 :
2177 : GGadgetsCreate(dv->dv,gcd);
2178 : GGadgetGetSize(gcd[6].ret,&size);
2179 : {
2180 : int diff = size.y+size.height+2 - dv->toph;
2181 : dv->toph = size.y+size.height+2;
2182 : GGadgetGetSize(gcd[0].ret,&size);
2183 : GGadgetMove(gcd[0].ret,size.x,size.y+diff);
2184 : GGadgetResize(gcd[0].ret,size.width,size.height-diff);
2185 : }
2186 :
2187 : GGadgetGetSize(gcd[0].ret,&size);
2188 : dv->ii.vsb = gcd[0].ret;
2189 : dv->ii.sbw = size.width;
2190 : dv->ii.vheight = size.height; dv->ii.vwidth = pos.width-sbsize;
2191 : dv->ii.showaddr = true;
2192 : dv->ii.userdata = dv;
2193 : dv->ii.selection_callback = DVToggleBp;
2194 : dv->ii.bpcheck = DVBpCheck;
2195 : dv->ii.handle_char = DV_HandleChar;
2196 :
2197 : pos.y = dv->toph;
2198 : pos.width -= sbsize; pos.height -= pos.y;
2199 : dv->ii.v = GWidgetCreateSubWindow(dv->dv,&pos,ii_v_e_h,&dv->ii,&wattrs);
2200 : dv->ii.instrdata = &dv->id;
2201 :
2202 : if ( monofont==NULL ) {
2203 : memset(&rq,0,sizeof(rq));
2204 : rq.utf8_family_name = MONO_UI_FAMILIES;
2205 : rq.point_size = -12;
2206 : rq.weight = 400;
2207 : monofont = GDrawInstanciateFont(cv->gw,&rq);
2208 : monofont = GResourceFindFont("DebugView.Font",monofont);
2209 : }
2210 : dv->ii.gfont = monofont;
2211 : GDrawSetFont(dv->ii.v,dv->ii.gfont);
2212 : GDrawWindowFontMetrics(dv->ii.v,dv->ii.gfont,&as,&ds,&ld);
2213 : dv->ii.as = as+1;
2214 : dv->ii.fh = dv->ii.as+ds;
2215 : dv->ii.isel_pos = -1;
2216 :
2217 : if (( exc = DebuggerGetEContext(dv->dc))!=NULL )
2218 : DVFigureNewState(dv,exc);
2219 : else
2220 : DVDefaultRaster(dv);
2221 : GDrawSetVisible(dv->ii.v,true);
2222 : GDrawSetVisible(dv->dv,true);
2223 : CVResize(cv);
2224 : GDrawRequestExpose(cv->v,NULL,false);
2225 : for ( i=0; wcreat[i].create!=NULL; ++i ) {
2226 : if ( debug_wins & wcreat[i].flag )
2227 : (wcreat[i].create)(dv);
2228 : }
2229 : } else {
2230 : dv->scalex = scalex;
2231 : dv->scaley = scaley;
2232 : DebuggerReset(dv->dc,cv->ft_pointsizey,cv->ft_pointsizex,cv->ft_dpi,dbg_fpgm,cv->ft_depth==1);
2233 : FreeType_FreeRaster(cv->raster); cv->raster = NULL;
2234 : if (( exc = DebuggerGetEContext(dv->dc))!=NULL )
2235 : DVFigureNewState(dv,exc);
2236 : else
2237 : DVDefaultRaster(dv);
2238 : }
2239 : }
2240 :
2241 : void CVDebugPointPopup(CharView *cv) {
2242 : DebugView *dv = cv->dv;
2243 : TT_ExecContext exc = DebuggerGetEContext(dv->dc);
2244 : TT_GlyphZoneRec *r;
2245 : FT_Vector *pts;
2246 : int i,l,n;
2247 : int32 x,y,fudge;
2248 : char cspace[210];
2249 : extern float snapdistance;
2250 :
2251 : if ( exc==NULL )
2252 : goto no_point;
2253 : r = &exc->pts;
2254 : n = r->n_points;
2255 : pts = r->cur;
2256 :
2257 : x = rint(cv->info.x/dv->scalex);
2258 : y = rint(cv->info.y/dv->scaley);
2259 :
2260 : fudge = rint(snapdistance/cv->scale/dv->scaley);
2261 : for ( i=n-1; i>=0; --i ) {
2262 : if ( x>=pts[i].x-fudge && x<=pts[i].x+fudge &&
2263 : y>=pts[i].y-fudge && y<=pts[i].y+fudge )
2264 : break;
2265 : }
2266 : if ( i!=-1 ) {
2267 : snprintf(cspace,sizeof(cspace),
2268 : "Point %d %s-curve\nCur (em): %7.2f,%7.2f\nCur (px): %7.2f,%7.2f\nOrg (em): %7.2f,%7.2f",
2269 : i, r->tags[i]&FT_Curve_Tag_On?"On":"Off",
2270 : pts[i].x*dv->scalex, pts[i].y*dv->scaley,
2271 : pts[i].x/64.0, pts[i].y/64.0,
2272 : r->org[i].x*dv->scalex, r->org[i].y*dv->scaley );
2273 : } else {
2274 : int xx, yy;
2275 : for ( i=n-1; i>=0; --i ) {
2276 : l = i==0?n-1:i-1;
2277 : if ( !(r->tags[i]&FT_Curve_Tag_On) && !(r->tags[l]&FT_Curve_Tag_On)) {
2278 : xx = (pts[i].x+pts[l].x)/2; yy = (pts[i].y+pts[l].y)/2;
2279 : if ( x>=xx-fudge && x<=xx+fudge &&
2280 : y>=yy-fudge && y<=yy+fudge )
2281 : break;
2282 : }
2283 : }
2284 : if ( i==-1 )
2285 : goto no_point;
2286 : snprintf(cspace,sizeof(cspace),
2287 : "Interpolated between %d %d\nCur (em): %7.2f,%7.2f\nCur (px): %7.2f,%7.2f\nOrg (em): %7.2f,%7.2f",
2288 : l,i,
2289 : xx*dv->scalex, yy*dv->scaley,
2290 : xx/64.0, yy/64.0,
2291 : (r->org[i].x+r->org[l].x)*dv->scalex/2.0, (r->org[i].y+r->org[l].y)*dv->scaley/2.0 );
2292 : }
2293 : goto showit;
2294 :
2295 : no_point:
2296 : snprintf(cspace,sizeof(cspace),
2297 : "%.2f, %.2f", (double) (cv->info.x/dv->scalex/64.0), (double) (cv->info.y/dv->scaley/64.0) );
2298 :
2299 : showit:
2300 : if ( cv->raster!=NULL ) {
2301 : int x = cv->info.x/dv->scalex/64.0 - cv->raster->lb;
2302 : int y = cv->raster->as-cv->info.y/dv->scaley/64.0;
2303 : int val;
2304 : if ( cv->raster->num_greys>2 ) {
2305 : if ( x<0 || x>=cv->raster->cols || y<0 || y>=cv->raster->rows )
2306 : val = 0; /* Not in raster */
2307 : else
2308 : val = cv->raster->bitmap[y*cv->raster->bytes_per_row+x];
2309 : snprintf(cspace+strlen(cspace),sizeof(cspace)-strlen(cspace),
2310 : "\nRaster grey=0x%02x (%.2f)", val, val/256.0 );
2311 : } else {
2312 : if ( x<0 || x>=cv->raster->cols || y<0 || y>=cv->raster->rows )
2313 : val = 0;
2314 : else
2315 : val = cv->raster->bitmap[y*cv->raster->bytes_per_row+(x>>3)] & (1<<(7-(x&7)));
2316 : if ( val )
2317 : strcat(cspace, "\nRaster On");
2318 : else
2319 : strcat(cspace, "\nRaster Off");
2320 : }
2321 : }
2322 : if ( cv->oldraster!=NULL ) {
2323 : int x = cv->info.x/dv->scalex/64.0 - cv->oldraster->lb;
2324 : int y = cv->oldraster->as-cv->info.y/dv->scaley/64.0;
2325 : int val;
2326 : if ( cv->oldraster->num_greys>2 ) {
2327 : if ( x<0 || x>=cv->oldraster->cols || y<0 || y>=cv->oldraster->rows )
2328 : val = 0;
2329 : else
2330 : val = cv->oldraster->bitmap[y*cv->oldraster->bytes_per_row+x];
2331 : snprintf(cspace+strlen(cspace),sizeof(cspace)-strlen(cspace),
2332 : "\nOld Raster grey=0x%02x (%.2f)", val, val/256.0 );
2333 : } else {
2334 : if ( x<0 || x>=cv->oldraster->cols || y<0 || y>=cv->oldraster->rows )
2335 : val = 0;
2336 : else
2337 : val = cv->oldraster->bitmap[y*cv->oldraster->bytes_per_row+(x>>3)] & (1<<(7-(x&7)));
2338 : if ( val )
2339 : strcat(cspace, "\nOld Raster On");
2340 : else
2341 : strcat(cspace, "\nOld Raster Off");
2342 : }
2343 : }
2344 : GGadgetPreparePopup8(cv->v,cspace);
2345 : }
2346 : #endif
|