LCOV - code coverage report
Current view: top level - fontforgeexe - freetypeui.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 0 29 0.0 %
Date: 2017-08-04 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2000-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             :  * derived 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 "fontforgeui.h"
      28             : #include "fffreetype.h"
      29             : #include "edgelist2.h"
      30             : #include <gwidget.h>
      31             : #include <ustring.h>
      32             : #include <math.h>
      33             : 
      34             : /******************************************************************************/
      35             : /* ***************************** Debugger Stuff ***************************** */
      36             : /******************************************************************************/
      37             : 
      38             : #if FREETYPE_HAS_DEBUGGER
      39             : #include <pthread.h>
      40             : #include <tterrors.h>
      41             : 
      42             : typedef struct bpdata {
      43             :     int range;  /* tt_coderange_glyph, tt_coderange_font, tt_coderange_cvt */
      44             :     int ip;
      45             : } BpData;
      46             : 
      47             : struct debugger_context {
      48             :     FT_Library context;
      49             :     FTC *ftc;
      50             :     /* I use a thread because freetype doesn't return, it just has a callback */
      51             :     /*  on each instruction. In actuallity only one thread should be executable*/
      52             :     /*  at a time (either main, or child) */
      53             :     pthread_t thread;
      54             :     pthread_mutex_t parent_mutex, child_mutex;
      55             :     pthread_cond_t parent_cond, child_cond;
      56             :     unsigned int terminate: 1;          /* The thread has been started simply to clean itself up and die */
      57             :     unsigned int has_mutexes: 1;
      58             :     unsigned int has_thread: 1;
      59             :     unsigned int has_finished: 1;
      60             :     unsigned int debug_fpgm: 1;
      61             :     unsigned int multi_step: 1;
      62             :     unsigned int found_wp: 1;
      63             :     unsigned int found_wps: 1;
      64             :     unsigned int found_wps_uninit: 1;
      65             :     unsigned int found_wpc: 1;
      66             :     unsigned int initted_pts: 1;
      67             :     unsigned int is_bitmap: 1;
      68             :     int wp_ptindex, wp_cvtindex, wp_storeindex;
      69             :     real ptsizey, ptsizex;
      70             :     int dpi;
      71             :     TT_ExecContext exc;
      72             :     SplineChar *sc;
      73             :     int layer;
      74             :     BpData temp;
      75             :     BpData breaks[32];
      76             :     int bcnt;
      77             :     FT_Vector *oldpts;
      78             :     FT_Long *oldstore;
      79             :     uint8 *storetouched;
      80             :     int storeSize;
      81             :     FT_Long *oldcvt;
      82             :     FT_Long oldsval, oldcval;
      83             :     int n_points;
      84             :     uint8 *watch;               /* exc->pts.n_points */
      85             :     uint8 *watchstorage;        /* exc->storeSize, exc->storage[i] */
      86             :     uint8 *watchcvt;            /* exc->cvtSize, exc->cvt[i] */
      87             :     int uninit_index;
      88             : };
      89             : 
      90             : static int AtWp(struct debugger_context *dc, TT_ExecContext exc ) {
      91             :     int i, hit=false, h;
      92             : 
      93             :     dc->found_wp = false;
      94             :     if ( dc->watch!=NULL && dc->oldpts!=NULL ) {
      95             :         for ( i=0; i<exc->pts.n_points; ++i ) {
      96             :             if ( dc->oldpts[i].x!=exc->pts.cur[i].x || dc->oldpts[i].y!=exc->pts.cur[i].y ) {
      97             :                 dc->oldpts[i] = exc->pts.cur[i];
      98             :                 if ( dc->watch[i] ) {
      99             :                     hit = true;
     100             :                     dc->wp_ptindex = i;
     101             :                 }
     102             :             }
     103             :         }
     104             :         dc->found_wp = hit;
     105             :     }
     106             :     if ( dc->found_wps_uninit )
     107             :         hit = true;
     108             :     dc->found_wps = false;
     109             :     if ( dc->watchstorage!=NULL && dc->storetouched!=NULL ) {
     110             :         h = false;
     111             :         for ( i=0; i<exc->storeSize; ++i ) {
     112             :             if ( dc->storetouched[i]&2 ) {
     113             :                 if ( dc->watchstorage[i] ) {
     114             :                     h = true;
     115             :                     dc->wp_storeindex = i;
     116             :                     dc->oldsval = dc->oldstore[i];
     117             :                 }
     118             :                 dc->storetouched[i]&=~2;
     119             :                 dc->oldstore[i] = exc->storage[i];
     120             :             }
     121             :         }
     122             :         dc->found_wps = h;
     123             :         hit |= h;
     124             :     }
     125             :     dc->found_wpc = false;
     126             :     if ( dc->watchcvt!=NULL && dc->oldcvt!=NULL ) {
     127             :         h = false;
     128             :         for ( i=0; i<exc->cvtSize; ++i ) {
     129             :             if ( dc->oldcvt[i]!=exc->cvt[i] ) {
     130             :                 if ( dc->watchcvt[i] ) {
     131             :                     h = true;
     132             :                     dc->wp_cvtindex = i;
     133             :                     dc->oldcval = dc->oldcvt[i];
     134             :                 }
     135             :                 dc->oldcvt[i] = exc->cvt[i];
     136             :             }
     137             :         }
     138             :         dc->found_wpc = h;
     139             :         hit |= h;
     140             :     }
     141             : return( hit );
     142             : }
     143             : 
     144             : static int AtBp(struct debugger_context *dc, TT_ExecContext exc ) {
     145             :     int i;
     146             : 
     147             :     if ( dc->temp.range==exc->curRange && dc->temp.ip==exc->IP ) {
     148             :         dc->temp.range = tt_coderange_none;
     149             : return( true );
     150             :     }
     151             : 
     152             :     for ( i=0; i<dc->bcnt; ++i ) {
     153             :         if ( dc->breaks[i].range==exc->curRange && dc->breaks[i].ip==exc->IP )
     154             : return( true );
     155             :     }
     156             : return( false );
     157             : }
     158             : 
     159             : static void TestStorage( struct debugger_context *dc, TT_ExecContext exc) {
     160             :     int instr;
     161             : 
     162             :     if ( exc->code==NULL || exc->IP==exc->codeSize )
     163             : return;
     164             :     instr = exc->code[exc->IP];
     165             :     if ( instr==0x42 /* Write store */ && exc->top>=2 ) {
     166             :         int store_index = exc->stack[exc->top-2];
     167             :         if ( store_index>=0 && store_index<exc->storeSize )
     168             :             dc->storetouched[store_index] = 3;       /* 2=>written this instr, 1=>ever written */
     169             :     } else if ( instr==0x43 /* Read Store */ && exc->top>=1 ) {
     170             :         int store_index = exc->stack[exc->top-1];
     171             :         if ( store_index>=0 && store_index<exc->storeSize &&
     172             :                 !dc->storetouched[store_index] &&
     173             :                 dc->watchstorage!=NULL && dc->watchstorage[store_index] ) {
     174             :             dc->found_wps_uninit = true;
     175             :             dc->uninit_index = store_index;
     176             :         }
     177             :     }
     178             : }
     179             : 
     180             : static struct debugger_context *massive_kludge;
     181             : 
     182             : static FT_Error PauseIns( TT_ExecContext exc ) {
     183             :     int ret;
     184             :     struct debugger_context *dc = massive_kludge;
     185             : 
     186             :     if ( dc->terminate )
     187             : return( TT_Err_Execution_Too_Long );            /* Some random error code, says we're probably in a infinite loop */
     188             :     dc->exc = exc;
     189             :     exc->grayscale = !dc->is_bitmap;              /* if we are in 'prep' or 'fpgm' freetype doesn't know this yet */
     190             : 
     191             :     /* Set up for watch points */
     192             :     if ( dc->oldpts==NULL && exc->pts.n_points!=0 ) {
     193             :         dc->oldpts = calloc(exc->pts.n_points,sizeof(FT_Vector));
     194             :         dc->n_points = exc->pts.n_points;
     195             :     }
     196             :     if ( dc->oldstore==NULL && exc->storeSize!=0 ) {
     197             :         dc->oldstore = calloc(exc->storeSize,sizeof(FT_Long));
     198             :         dc->storetouched = calloc(exc->storeSize,sizeof(uint8));
     199             :         dc->storeSize = exc->storeSize;
     200             :     }
     201             :     if ( dc->oldcvt==NULL && exc->cvtSize!=0 )
     202             :         dc->oldcvt = calloc(exc->cvtSize,sizeof(FT_Long));
     203             :     if ( !dc->initted_pts ) {
     204             :         AtWp(dc,exc);
     205             :         dc->found_wp = false;
     206             :         dc->found_wps = false;
     207             :         dc->found_wps_uninit = false;
     208             :         dc->found_wpc = false;
     209             :         dc->initted_pts = true;
     210             :     }
     211             : 
     212             :     if ( !dc->debug_fpgm && exc->curRange!=tt_coderange_glyph ) {
     213             :         exc->instruction_trap = 1;
     214             :         ret = 0;
     215             :         while ( exc->curRange!=tt_coderange_glyph ) {
     216             :             TestStorage(dc,exc);
     217             :             ret = TT_RunIns(exc);
     218             :             if ( ret==TT_Err_Code_Overflow )
     219             : return( 0 );
     220             :             if ( ret )
     221             : return( ret );
     222             :         }
     223             : return( ret );
     224             :     }
     225             : 
     226             :     pthread_mutex_lock(&dc->parent_mutex);
     227             :     pthread_cond_signal(&dc->parent_cond);
     228             :     pthread_mutex_unlock(&dc->parent_mutex);
     229             :     pthread_cond_wait(&dc->child_cond,&dc->child_mutex);
     230             :     if ( dc->terminate )
     231             : return( TT_Err_Execution_Too_Long );
     232             : 
     233             :     do {
     234             :         exc->instruction_trap = 1;
     235             :         if (exc->curRange==tt_coderange_glyph && exc->IP==exc->codeSize) {
     236             :             ret = TT_Err_Code_Overflow;
     237             :     break;
     238             :         }
     239             :         TestStorage(dc,exc);
     240             :         ret = TT_RunIns(exc);
     241             :         if ( ret )
     242             :     break;
     243             :         /* Signal the parent if we are single stepping, or if we've reached a break-point */
     244             :         if ( AtWp(dc,exc) || !dc->multi_step || AtBp(dc,exc) ||
     245             :                 (exc->curRange==tt_coderange_glyph && exc->IP==exc->codeSize)) {
     246             :             if ( dc->found_wp ) {
     247             :                 ff_post_notice(_("Hit Watch Point"),_("Point %d was moved by the previous instruction"),dc->wp_ptindex);
     248             :                 dc->found_wp = false;
     249             :             }
     250             :             if ( dc->found_wps ) {
     251             :                 ff_post_notice(_("Watched Store Change"),_("Storage %d was changed from %d (%.2f) to %d (%.2f) by the previous instruction"),
     252             :                         dc->wp_storeindex, dc->oldsval, dc->oldsval/64.0,exc->storage[dc->wp_storeindex],exc->storage[dc->wp_storeindex]/64.0);
     253             :                 dc->found_wps = false;
     254             :             }
     255             :             if ( dc->found_wps_uninit ) {
     256             :                 ff_post_notice(_("Read of Uninitialized Store"),_("Storage %d has not been initialized, yet the previous instruction read it"),
     257             :                         dc->uninit_index );
     258             :                 dc->found_wps_uninit = false;
     259             :             }
     260             :             if ( dc->found_wpc ) {
     261             :                 ff_post_notice(_("Watched Cvt Change"),_("Cvt %d was changed from %d (%.2f) to %d (%.2f) by the previous instruction"),
     262             :                         dc->wp_cvtindex, dc->oldcval, dc->oldcval/64.0,exc->cvt[dc->wp_cvtindex],exc->cvt[dc->wp_cvtindex]/64.0);
     263             :                 dc->found_wpc = false;
     264             :             }
     265             :             pthread_mutex_lock(&dc->parent_mutex);
     266             :             pthread_cond_signal(&dc->parent_cond);
     267             :             pthread_mutex_unlock(&dc->parent_mutex);
     268             :             pthread_cond_wait(&dc->child_cond,&dc->child_mutex);
     269             :         }
     270             :     } while ( !dc->terminate );
     271             : 
     272             :     if ( ret==TT_Err_Code_Overflow )
     273             :         ret = 0;
     274             : 
     275             :     massive_kludge = dc;        /* We set this again in case we are in a composite character where I think we get called several times (and some other thread might have set it) */
     276             :     if ( dc->terminate )
     277             : return( TT_Err_Execution_Too_Long );
     278             : 
     279             : return( ret );
     280             : }
     281             : 
     282             : static void *StartChar(void *_dc) {
     283             :     struct debugger_context *dc = _dc;
     284             : 
     285             :     pthread_mutex_lock(&dc->child_mutex);
     286             : 
     287             :     massive_kludge = dc;
     288             :     if ( (dc->ftc = __FreeTypeFontContext(dc->context,dc->sc->parent,dc->sc,NULL,
     289             :             dc->layer,ff_ttf, 0, NULL))==NULL )
     290             :  goto finish;
     291             :     if ( dc->storetouched!=NULL )
     292             :         memset(dc->storetouched,0,dc->storeSize);
     293             : 
     294             :     massive_kludge = dc;
     295             :     if ( FT_Set_Char_Size(dc->ftc->face,(int) (dc->ptsizex*64),(int) (dc->ptsizey*64), dc->dpi, dc->dpi))
     296             :  goto finish;
     297             : 
     298             :     massive_kludge = dc;
     299             :     FT_Load_Glyph(dc->ftc->face,dc->ftc->glyph_indeces[dc->sc->orig_pos],
     300             :             dc->is_bitmap ? (FT_LOAD_NO_AUTOHINT|FT_LOAD_NO_BITMAP|FT_LOAD_TARGET_MONO) : (FT_LOAD_NO_AUTOHINT|FT_LOAD_NO_BITMAP));
     301             : 
     302             :  finish:
     303             :     dc->has_finished = true;
     304             :     dc->exc = NULL;
     305             :     pthread_mutex_lock(&dc->parent_mutex);
     306             :     pthread_cond_signal(&dc->parent_cond);       /* Wake up parent and get it to clean up after itself */
     307             :     pthread_mutex_unlock(&dc->parent_mutex);
     308             :     pthread_mutex_unlock(&dc->child_mutex);
     309             : return( NULL );
     310             : }
     311             : 
     312             : void DebuggerTerminate(struct debugger_context *dc) {
     313             :     if ( dc->has_thread ) {
     314             :         if ( !dc->has_finished ) {
     315             :             dc->terminate = true;
     316             :             pthread_mutex_lock(&dc->child_mutex);
     317             :             pthread_cond_signal(&dc->child_cond);        /* Wake up child and get it to clean up after itself */
     318             :             pthread_mutex_unlock(&dc->child_mutex);
     319             :             pthread_mutex_unlock(&dc->parent_mutex);
     320             :         }
     321             :         pthread_join(dc->thread,NULL);
     322             :         dc->has_thread = false;
     323             :     }
     324             :     if ( dc->has_mutexes ) {
     325             :         pthread_cond_destroy(&dc->child_cond);
     326             :         pthread_cond_destroy(&dc->parent_cond);
     327             :         pthread_mutex_destroy(&dc->child_mutex);
     328             :         pthread_mutex_unlock(&dc->parent_mutex); /* Is this actually needed? */
     329             :         pthread_mutex_destroy(&dc->parent_mutex);
     330             :     }
     331             :     if ( dc->ftc!=NULL )
     332             :         FreeTypeFreeContext(dc->ftc);
     333             :     if ( dc->context!=NULL )
     334             :         FT_Done_FreeType( dc->context );
     335             :     free(dc->watch);
     336             :     free(dc->oldpts);
     337             :     free(dc);
     338             : }
     339             : 
     340             : void DebuggerReset(struct debugger_context *dc,real ptsizey, real ptsizex,int dpi,int dbg_fpgm, int is_bitmap) {
     341             :     /* Kill off the old thread, and start up a new one working on the given */
     342             :     /*  pointsize and resolution */ /* I'm not prepared for errors here */
     343             :     /* Note that if we don't want to look at the fpgm/prep code (and we */
     344             :     /*  usually don't) then we must turn off the debug hook when they get run */
     345             : 
     346             :     if ( dc->has_thread ) {
     347             :         dc->terminate = true;
     348             :         pthread_mutex_lock(&dc->child_mutex);
     349             :         pthread_cond_signal(&dc->child_cond);    /* Wake up child and get it to clean up after itself */
     350             :         pthread_mutex_unlock(&dc->child_mutex);
     351             :         pthread_mutex_unlock(&dc->parent_mutex);
     352             : 
     353             :         pthread_join(dc->thread,NULL);
     354             :         dc->has_thread = false;
     355             :     }
     356             :     if ( dc->ftc!=NULL )
     357             :         FreeTypeFreeContext(dc->ftc);
     358             : 
     359             :     dc->debug_fpgm = dbg_fpgm;
     360             :     dc->ptsizey = ptsizey;
     361             :     dc->ptsizex = ptsizex;
     362             :     dc->dpi = dpi;
     363             :     dc->is_bitmap = is_bitmap;
     364             :     dc->terminate = dc->has_finished = false;
     365             :     dc->initted_pts = false;
     366             : 
     367             :     pthread_mutex_lock(&dc->parent_mutex);
     368             :     if ( pthread_create(&dc->thread,NULL,StartChar,(void *) dc)!=0 ) {
     369             :         DebuggerTerminate(dc);
     370             : return;
     371             :     }
     372             :     if ( dc->has_finished )
     373             : return;
     374             :     dc->has_thread = true;
     375             :     pthread_cond_wait(&dc->parent_cond,&dc->parent_mutex);
     376             : }
     377             : 
     378             : struct debugger_context *DebuggerCreate(SplineChar *sc,int layer, real ptsizey,real ptsizex,int dpi,int dbg_fpgm, int is_bitmap) {
     379             :     struct debugger_context *dc;
     380             : 
     381             :     if ( !hasFreeTypeDebugger())
     382             : return( NULL );
     383             : 
     384             :     dc = calloc(1,sizeof(struct debugger_context));
     385             :     dc->sc = sc;
     386             :     dc->layer = layer;
     387             :     dc->debug_fpgm = dbg_fpgm;
     388             :     dc->ptsizey = ptsizey;
     389             :     dc->ptsizex = ptsizex;
     390             :     dc->dpi = dpi;
     391             :     dc->is_bitmap = is_bitmap;
     392             :     if ( FT_Init_FreeType( &dc->context )) {
     393             :         free(dc);
     394             : return( NULL );
     395             :     }
     396             : 
     397             : #if FREETYPE_MINOR >= 5
     398             :     {
     399             :         int tt_version = TT_INTERPRETER_VERSION_35;
     400             : 
     401             :         if ( FT_Property_Set( dc->context,
     402             :                               "truetype",
     403             :                               "interpreter-version",
     404             :                               &tt_version )) {
     405             :             free(dc);
     406             : return( NULL );
     407             :         }
     408             :     }
     409             : #endif
     410             : 
     411             :     FT_Set_Debug_Hook( dc->context,
     412             :                        FT_DEBUG_HOOK_TRUETYPE,
     413             :                        (FT_DebugHook_Func)PauseIns );
     414             : 
     415             :     pthread_mutex_init(&dc->parent_mutex,NULL); pthread_mutex_init(&dc->child_mutex,NULL);
     416             :     pthread_cond_init(&dc->parent_cond,NULL); pthread_cond_init(&dc->child_cond,NULL);
     417             :     dc->has_mutexes = true;
     418             : 
     419             :     pthread_mutex_lock(&dc->parent_mutex);
     420             :     if ( pthread_create(&dc->thread,NULL,StartChar,dc)!=0 ) {
     421             :         DebuggerTerminate( dc );
     422             : return( NULL );
     423             :     }
     424             :     dc->has_thread = true;
     425             :     pthread_cond_wait(&dc->parent_cond,&dc->parent_mutex);        /* Wait for the child to initialize itself (and stop) then we can look at its status */
     426             : 
     427             : return( dc );
     428             : }
     429             : 
     430             : void DebuggerGo(struct debugger_context *dc,enum debug_gotype dgt,DebugView *dv) {
     431             :     int opcode;
     432             : 
     433             :     if ( !dc->has_thread || dc->has_finished || dc->exc==NULL ) {
     434             :         FreeType_FreeRaster(dv->cv->raster); dv->cv->raster = NULL;
     435             :         DebuggerReset(dc,dc->ptsizey,dc->ptsizex,dc->dpi,dc->debug_fpgm,dc->is_bitmap);
     436             :     } else {
     437             :         switch ( dgt ) {
     438             :           case dgt_continue:
     439             :             dc->multi_step = true;
     440             :           break;
     441             :           case dgt_stepout:
     442             :             dc->multi_step = true;
     443             :             if ( dc->exc->callTop>0 ) {
     444             :                 dc->temp.range = dc->exc->callStack[dc->exc->callTop-1].Caller_Range;
     445             :                 dc->temp.ip = dc->exc->callStack[dc->exc->callTop-1].Caller_IP;
     446             :             }
     447             :           break;
     448             :           case dgt_next:
     449             :             opcode = dc->exc->code[dc->exc->IP];
     450             :             /* I've decided that IDEFs will get stepped into */
     451             :             if ( opcode==0x2b /* call */ || opcode==0x2a /* loopcall */ ) {
     452             :                 dc->temp.range = dc->exc->curRange;
     453             :                 dc->temp.ip = dc->exc->IP+1;
     454             :                 dc->multi_step = true;
     455             :             } else
     456             :                 dc->multi_step = false;
     457             :           break;
     458             :           default:
     459             :           case dgt_step:
     460             :             dc->multi_step = false;
     461             :           break;
     462             :         }
     463             :         pthread_mutex_lock(&dc->child_mutex);
     464             :         pthread_cond_signal(&dc->child_cond);    /* Wake up child and get it to clean up after itself */
     465             :         pthread_mutex_unlock(&dc->child_mutex);
     466             :         pthread_cond_wait(&dc->parent_cond,&dc->parent_mutex);    /* Wait for the child to initialize itself (and stop) then we can look at its status */
     467             :     }
     468             : }
     469             : 
     470             : struct TT_ExecContextRec_ *DebuggerGetEContext(struct debugger_context *dc) {
     471             : return( dc->exc );
     472             : }
     473             : 
     474             : int DebuggerBpCheck(struct debugger_context *dc,int range,int ip) {
     475             :     int i;
     476             : 
     477             :     for ( i=0; i<dc->bcnt; ++i ) {
     478             :         if ( dc->breaks[i].range==range && dc->breaks[i].ip==ip )
     479             : return( true );
     480             :     }
     481             : return( false );
     482             : }
     483             : 
     484             : void DebuggerToggleBp(struct debugger_context *dc,int range,int ip) {
     485             :     int i;
     486             : 
     487             :     /* If the address has a bp, then remove it */
     488             :     for ( i=0; i<dc->bcnt; ++i ) {
     489             :         if ( dc->breaks[i].range==range && dc->breaks[i].ip==ip ) {
     490             :             ++i;
     491             :             while ( i<dc->bcnt ) {
     492             :                 dc->breaks[i-1].range = dc->breaks[i].range;
     493             :                 dc->breaks[i-1].ip = dc->breaks[i].ip;
     494             :                 ++i;
     495             :             }
     496             :             --dc->bcnt;
     497             : return;
     498             :         }
     499             :     }
     500             :     /* Else add it */
     501             :     if ( dc->bcnt>=sizeof(dc->breaks)/sizeof(dc->breaks[0]) ) {
     502             :         ff_post_error(_("Too Many Breakpoints"),_("Too Many Breakpoints"));
     503             : return;
     504             :     }
     505             :     i = dc->bcnt++;
     506             :     dc->breaks[i].range = range;
     507             :     dc->breaks[i].ip = ip;
     508             : }
     509             : 
     510             : void DebuggerSetWatches(struct debugger_context *dc,int n, uint8 *w) {
     511             :     free(dc->watch); dc->watch=NULL;
     512             :     if ( n!=dc->n_points ) IError("Bad watchpoint count");
     513             :     else {
     514             :         dc->watch = w;
     515             :         if ( dc->exc ) {
     516             :             AtWp(dc,dc->exc);
     517             :             dc->found_wp = false;
     518             :             dc->found_wpc = false;
     519             :             dc->found_wps = false;
     520             :             dc->found_wps_uninit = false;
     521             :         }
     522             :     }
     523             : }
     524             : 
     525             : uint8 *DebuggerGetWatches(struct debugger_context *dc, int *n) {
     526             :     *n = dc->n_points;
     527             : return( dc->watch );
     528             : }
     529             : 
     530             : void DebuggerSetWatchStores(struct debugger_context *dc,int n, uint8 *w) {
     531             :     free(dc->watchstorage); dc->watchstorage=NULL;
     532             :     if ( n!=dc->exc->storeSize ) IError("Bad watchpoint count");
     533             :     else {
     534             :         dc->watchstorage = w;
     535             :         if ( dc->exc ) {
     536             :             AtWp(dc,dc->exc);
     537             :             dc->found_wp = false;
     538             :             dc->found_wpc = false;
     539             :             dc->found_wps = false;
     540             :             dc->found_wps_uninit = false;
     541             :         }
     542             :     }
     543             : }
     544             : 
     545             : uint8 *DebuggerGetWatchStores(struct debugger_context *dc, int *n) {
     546             :     *n = dc->exc->storeSize;
     547             : return( dc->watchstorage );
     548             : }
     549             : 
     550             : int DebuggerIsStorageSet(struct debugger_context *dc, int index) {
     551             :     if ( dc->storetouched==NULL )
     552             : return( false );
     553             : return( dc->storetouched[index]&1 );
     554             : }
     555             : 
     556             : void DebuggerSetWatchCvts(struct debugger_context *dc,int n, uint8 *w) {
     557             :     free(dc->watchcvt); dc->watchcvt=NULL;
     558             :     if ( n!=dc->exc->cvtSize ) IError("Bad watchpoint count");
     559             :     else {
     560             :         dc->watchcvt = w;
     561             :         if ( dc->exc ) {
     562             :             AtWp(dc,dc->exc);
     563             :             dc->found_wp = false;
     564             :             dc->found_wpc = false;
     565             :             dc->found_wps = false;
     566             :             dc->found_wps_uninit = false;
     567             :         }
     568             :     }
     569             : }
     570             : 
     571             : uint8 *DebuggerGetWatchCvts(struct debugger_context *dc, int *n) {
     572             :     *n = dc->exc->cvtSize;
     573             : return( dc->watchcvt );
     574             : }
     575             : 
     576             : int DebuggingFpgm(struct debugger_context *dc) {
     577             : return( dc->debug_fpgm );
     578             : }
     579             : 
     580             : struct freetype_raster *DebuggerCurrentRaster(TT_ExecContext exc,int depth) {
     581             :     FT_Outline outline;
     582             :     FT_Bitmap bitmap;
     583             :     int i, err, j, k, first, xoff, yoff;
     584             :     IBounds b;
     585             :     struct freetype_raster *ret;
     586             : 
     587             :     outline.n_contours = exc->pts.n_contours;
     588             :     outline.tags = (char *) exc->pts.tags;
     589             :     outline.contours = (short *) exc->pts.contours;
     590             :     /* Rasterizer gets unhappy if we give it the phantom points */
     591             :     if ( outline.n_contours==0 )
     592             :         outline.n_points = 0;
     593             :     else
     594             :         outline.n_points = /*exc->pts.n_points*/  outline.contours[outline.n_contours - 1] + 1;
     595             :     outline.points = exc->pts.cur;
     596             :     outline.flags = 0;
     597             :     switch ( exc->GS.scan_type ) {
     598             :       /* Taken, at Werner's suggestion, from the freetype sources: ttgload.c:1970 */
     599             :       case 0: /* simple drop-outs including stubs */
     600             :         outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
     601             :       break;
     602             :       case 1: /* simple drop-outs excluding stubs */
     603             :         /* nothing; it's the default rendering mode */
     604             :       break;
     605             :       case 4: /* smart drop-outs including stubs */
     606             :         outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
     607             :                                 FT_OUTLINE_INCLUDE_STUBS;
     608             :       break;
     609             :       case 5: /* smart drop-outs excluding stubs  */
     610             :         outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
     611             :       break;
     612             : 
     613             :       default: /* no drop-out control */
     614             :         outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
     615             :       break;
     616             :     }
     617             : 
     618             :     if ( exc->metrics.y_ppem < 24 )
     619             :        outline.flags |= FT_OUTLINE_HIGH_PRECISION;
     620             : 
     621             :     first = true;
     622             :     for ( k=0; k<outline.n_contours; ++k ) {
     623             :         if ( outline.contours[k] - (k==0?-1:outline.contours[k-1])>1 ) {
     624             :             /* Single point contours are used for things like point matching */
     625             :             /*  for anchor points, etc. and do not contribute to the bounding */
     626             :             /*  box */
     627             :             i = (k==0?0:(outline.contours[k-1]+1));
     628             :             if ( first ) {
     629             :                 b.minx = b.maxx = outline.points[i].x;
     630             :                 b.miny = b.maxy = outline.points[i++].y;
     631             :                 first = false;
     632             :             }
     633             :             for ( ; i<=outline.contours[k]; ++i ) {
     634             :                 if ( outline.points[i].x>b.maxx ) b.maxx = outline.points[i].x;
     635             :                 if ( outline.points[i].x<b.minx ) b.minx = outline.points[i].x;
     636             :                 if ( outline.points[i].y>b.maxy ) b.maxy = outline.points[i].y;
     637             :                 if ( outline.points[i].y<b.miny ) b.miny = outline.points[i].y;
     638             :             }
     639             :         }
     640             :     }
     641             :     if ( first )
     642             :         memset(&b,0,sizeof(b));
     643             : 
     644             :     memset(&bitmap,0,sizeof(bitmap));
     645             :     bitmap.rows = (((int) (ceil(b.maxy/64.0)-floor(b.miny/64.0)))) +1;
     646             :     bitmap.width = (((int) (ceil(b.maxx/64.0)-floor(b.minx/64.0)))) +1;
     647             : 
     648             :     xoff = 64*floor(b.minx/64.0);
     649             :     yoff = 64*floor(b.miny/64.0);
     650             :     for ( i=0; i<outline.n_points; ++i ) {
     651             :         outline.points[i].x -= xoff;
     652             :         outline.points[i].y -= yoff;
     653             :     }
     654             : 
     655             :     if ( depth==8 ) {
     656             :         bitmap.pitch = bitmap.width;
     657             :         bitmap.num_grays = 256;
     658             :         bitmap.pixel_mode = ft_pixel_mode_grays;
     659             :     } else {
     660             :         bitmap.pitch = (bitmap.width+7)>>3;
     661             :         bitmap.num_grays = 0;
     662             :         bitmap.pixel_mode = ft_pixel_mode_mono;
     663             :     }
     664             :     bitmap.buffer = calloc(bitmap.pitch*bitmap.rows,sizeof(uint8));
     665             : 
     666             :     err = (FT_Outline_Get_Bitmap)(ff_ft_context,&outline,&bitmap);
     667             : 
     668             :     for ( i=0; i<outline.n_points; ++i ) {
     669             :         outline.points[i].x += xoff;
     670             :         outline.points[i].y += yoff;
     671             :     }
     672             : 
     673             :     ret = malloc(sizeof(struct freetype_raster));
     674             :     /* I'm not sure why I need these, but it seems I do */
     675             :     if ( depth==8 ) {
     676             :         ret->as = floor(b.miny/64.0) + bitmap.rows;
     677             :         ret->lb = floor(b.minx/64.0);
     678             :     } else {
     679             :         for ( k=0; k<bitmap.rows; ++k ) {
     680             :             for ( j=bitmap.pitch-1; j>=0 && bitmap.buffer[k*bitmap.pitch+j]==0; --j );
     681             :             if ( j!=-1 )
     682             :         break;
     683             :         }
     684             :         b.maxy += k<<6;
     685             :         if ( depth==8 ) {
     686             :             for ( j=0; j<bitmap.pitch; ++j ) {
     687             :                 for ( k=(((int) (b.maxy-b.miny))>>6)-1; k>=0; --k ) {
     688             :                     if ( bitmap.buffer[k*bitmap.pitch+j]!=0 )
     689             :                 break;
     690             :                 }
     691             :                 if ( k!=-1 )
     692             :             break;
     693             :             }
     694             :         } else {
     695             :             for ( j=0; j<bitmap.pitch; ++j ) {
     696             :                 for ( k=(((int) (b.maxy-b.miny))>>6)-1; k>=0; --k ) {
     697             :                     if ( bitmap.buffer[k*bitmap.pitch+(j>>3)]&(0x80>>(j&7)) )
     698             :                 break;
     699             :                 }
     700             :                 if ( k!=-1 )
     701             :             break;
     702             :             }
     703             :         }
     704             :         b.minx -= j*64;
     705             :         ret->as = rint(b.maxy/64.0);
     706             :         ret->lb = rint(b.minx/64.0);
     707             :     }
     708             :     ret->rows = bitmap.rows;
     709             :     ret->cols = bitmap.width;
     710             :     ret->bytes_per_row = bitmap.pitch;
     711             :     ret->num_greys = bitmap.num_grays;
     712             :     ret->bitmap = bitmap.buffer;
     713             : return( ret );
     714             : }
     715             :     
     716             : #else /* FIXME: Don't build this stuff if it's not being used, it just makes the compiler emit lots of warnings */
     717             : struct debugger_context;
     718             : 
     719           0 : void DebuggerTerminate(struct debugger_context *dc) {
     720           0 : }
     721             : 
     722           0 : void DebuggerReset(struct debugger_context *dc,real ptsizey, real ptsizex,int dpi,int dbg_fpgm, int is_bitmap) {
     723           0 : }
     724             : 
     725           0 : struct debugger_context *DebuggerCreate(SplineChar *sc,int layer,real pointsizey, real pointsizex,int dpi, int dbg_fpgm, int is_bitmap) {
     726           0 : return( NULL );
     727             : }
     728             : 
     729           0 : void DebuggerGo(struct debugger_context *dc,enum debug_gotype go,DebugView *dv) {
     730           0 : }
     731             : 
     732           0 : struct TT_ExecContextRec_ *DebuggerGetEContext(struct debugger_context *dc) {
     733           0 : return( NULL );
     734             : }
     735             : 
     736           0 : void DebuggerSetWatches(struct debugger_context *dc,int n, uint8 *w) {
     737           0 : }
     738             : 
     739           0 : uint8 *DebuggerGetWatches(struct debugger_context *dc, int *n) {
     740           0 :     *n = 0;
     741           0 : return( NULL );
     742             : }
     743             : 
     744           0 : void DebuggerSetWatchStores(struct debugger_context *dc,int n, uint8 *w) {
     745           0 : }
     746             : 
     747           0 : uint8 *DebuggerGetWatchStores(struct debugger_context *dc, int *n) {
     748           0 :     *n = 0;
     749           0 : return( NULL );
     750             : }
     751             : 
     752           0 : int DebuggerIsStorageSet(struct debugger_context *dc, int index) {
     753           0 : return( false );
     754             : }
     755             : 
     756           0 : void DebuggerSetWatchCvts(struct debugger_context *dc,int n, uint8 *w) {
     757           0 : }
     758             : 
     759           0 : uint8 *DebuggerGetWatchCvts(struct debugger_context *dc, int *n) {
     760           0 :     *n = 0;
     761           0 : return( NULL );
     762             : }
     763             : 
     764           0 : int DebuggingFpgm(struct debugger_context *dc) {
     765           0 : return( false );
     766             : }
     767             : #endif  /* FREETYPE_HAS_DEBUGGER */

Generated by: LCOV version 1.10