remove auto kfrm for gang, btn2 select kfrm pos
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / resourcepixmap.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22
23
24 #include "arender.h"
25 #include "aedit.h"
26 #include "asset.h"
27 #include "asset.inc"
28 #include "automation.h"
29 #include "autos.h"
30 #include "bcsignals.h"
31 #include "cache.h"
32 #include "clip.h"
33 #include "bccmodels.h"
34 #include "datatype.h"
35 #include "edit.h"
36 #include "edits.h"
37 #include "edl.h"
38 #include "edlsession.h"
39 #include "file.h"
40 #include "filesystem.h"
41 #include "floatauto.h"
42 #include "floatautos.h"
43 #include "framecache.h"
44 #include "indexfile.h"
45 #include "language.h"
46 #include "localsession.h"
47 #include "mwindow.h"
48 #include "mwindowgui.h"
49 #include "renderengine.h"
50 #include "resourcethread.h"
51 #include "resourcepixmap.h"
52 #include "samples.h"
53 #include "theme.h"
54 #include "timelinepane.h"
55 #include "track.h"
56 #include "trackcanvas.h"
57 #include "transportque.h"
58 #include "vedit.h"
59 #include "vframe.h"
60 #include "wavecache.h"
61
62
63 ResourcePixmap::ResourcePixmap(MWindow *mwindow,
64         MWindowGUI *gui,
65         Edit *edit,
66         int pane_number,
67         int w,
68         int h)
69  : BC_Pixmap(gui, w, h)
70 {
71         reset();
72
73         this->mwindow = mwindow;
74         this->gui = gui;
75         this->pane_number = pane_number;
76         startsource = edit->startsource;
77         data_type = edit->track->data_type;
78         if( edit->asset ) {
79                 source_framerate = edit->asset->frame_rate;
80                 source_samplerate = edit->asset->sample_rate;
81         }
82         else
83         if( edit->nested_edl ) {
84                 source_framerate = edit->nested_edl->session->frame_rate;
85                 source_samplerate = edit->nested_edl->session->sample_rate;
86         }
87
88         project_framerate = edit->edl->session->frame_rate;
89         project_samplerate = edit->edl->session->sample_rate;
90         edit_id = edit->id;  pixmap_w = w;  pixmap_h = h;
91 }
92
93 ResourcePixmap::~ResourcePixmap()
94 {
95 }
96
97
98 void ResourcePixmap::reset()
99 {
100         edit_x = 0;
101         pixmap_x = 0;
102         pixmap_w = 0;
103         pixmap_h = 0;
104         zoom_sample = 0;
105         zoom_track = 0;
106         zoom_y = 0;
107         visible = 1;
108 }
109
110 void ResourcePixmap::resize(int w, int h)
111 {
112         int new_w = (w > get_w()) ? w : get_w();
113         int new_h = (h > get_h()) ? h : get_h();
114
115         BC_Pixmap::resize(new_w, new_h);
116 }
117
118 void ResourcePixmap::update_settings(Edit *edit,
119         int64_t edit_x, int64_t edit_w,
120         int64_t pixmap_x, int64_t pixmap_w, int64_t pixmap_h)
121 {
122         this->edit_id = edit->id;
123         this->edit_x = edit_x;
124         this->pixmap_x = pixmap_x;
125         this->pixmap_w = pixmap_w;
126         this->pixmap_h = pixmap_h;
127
128         startsource = edit->startsource;
129         if( edit->asset )
130                 source_framerate = edit->asset->frame_rate;
131         else
132         if( edit->nested_edl )
133                 source_framerate = edit->nested_edl->session->frame_rate;
134         if( edit->asset )
135                 source_samplerate = edit->asset->sample_rate;
136         else if( edit->nested_edl )
137                 source_samplerate = edit->nested_edl->session->sample_rate;
138
139         project_framerate = edit->edl->session->frame_rate;
140         project_samplerate = edit->edl->session->sample_rate;
141         zoom_sample = mwindow->edl->local_session->zoom_sample;
142         zoom_track = mwindow->edl->local_session->zoom_track;
143         zoom_y = mwindow->edl->local_session->zoom_y;
144 }
145
146 void ResourcePixmap::draw_data(TrackCanvas *canvas,
147         Edit *edit, int64_t edit_x, int64_t edit_w,
148         int64_t pixmap_x, int64_t pixmap_w, int64_t pixmap_h,
149         int mode, int indexes_only)
150 {
151 // Get new areas to fill in relative to pixmap
152 // Area to redraw relative to pixmap
153         int refresh_x = 0;
154         int refresh_w = 0;
155
156 // Ignore if called by resourcethread.
157 //      if( mode == IGNORE_THREAD ) return;
158
159         int y = 0;
160         if( edit->track->show_titles() )
161                 y += mwindow->theme->get_image("title_bg_data")->get_h();
162
163 // If want indexes only & index can't be drawn, don't do anything.
164         int need_redraw = 0;
165         int64_t index_zoom = 0;
166         Indexable *indexable = 0;
167         if( edit->asset ) indexable = edit->asset;
168         if( edit->nested_edl ) indexable = edit->nested_edl;
169         if( indexable && indexes_only ) {
170                 IndexFile indexfile(mwindow, indexable);
171                 if( !indexfile.open_index() ) {
172                         index_zoom = indexable->index_state->index_zoom;
173                         indexfile.close_index();
174                 }
175
176                 if( index_zoom ) {
177                         if( data_type == TRACK_AUDIO ) {
178                                 double asset_over_session = (double)indexable->get_sample_rate() /
179                                         mwindow->edl->session->sample_rate;
180                                 if( index_zoom <= mwindow->edl->local_session->zoom_sample *
181                                         asset_over_session )
182                                         need_redraw = 1;
183                         }
184                 }
185
186                 if( !need_redraw )
187                         return;
188         }
189
190 /* Incremental drawing is not possible with resource thread */
191 // Redraw everything
192         refresh_x = 0;
193         refresh_w = pixmap_w;
194
195 // Draw background image
196         if( refresh_w > 0 )
197                 mwindow->theme->draw_resource_bg(canvas,
198                         this,
199                         edit_x,
200                         edit_w,
201                         pixmap_x,
202                         refresh_x,
203                         y,
204                         refresh_x + refresh_w,
205                         mwindow->edl->local_session->zoom_track + y);
206 //printf("ResourcePixmap::draw_data 70\n");
207
208
209 // Draw media which already exists
210         Track *track = edit->track;
211         if( track->draw ) {
212                 switch( track->data_type )
213                 {
214                         case TRACK_AUDIO:
215                                 draw_audio_resource(canvas,
216                                         edit,
217                                         refresh_x,
218                                         refresh_w);
219                                 break;
220
221                         case TRACK_VIDEO:
222                                 draw_video_resource(canvas,
223                                         edit,
224                                         edit_x,
225                                         edit_w,
226                                         pixmap_x,
227                                         pixmap_w,
228                                         refresh_x,
229                                         refresh_w,
230                                         mode);
231                                 break;
232
233                         case TRACK_SUBTITLE:
234                                 draw_subttl_resource(canvas,
235                                         edit,
236                                         refresh_x,
237                                         refresh_w);
238                                 break;
239                 }
240         }
241 SET_TRACE
242 }
243
244 void ResourcePixmap::draw_title(TrackCanvas *canvas,
245         Edit *edit, int64_t edit_x, int64_t edit_w,
246         int64_t pixmap_x, int64_t pixmap_w)
247 {
248 // coords relative to pixmap
249         int64_t total_x = edit_x - pixmap_x, total_w = edit_w;
250         int64_t x = total_x, w = total_w;
251         int left_margin = 10;
252
253         if( x < 0 ) { w -= -x; x = 0; }
254         if( w > pixmap_w ) w -= w - pixmap_w;
255
256         canvas->draw_3segmenth(x, 0, w, total_x, total_w,
257                 mwindow->theme->get_image("title_bg_data"), this);
258
259 //      if( total_x > -BC_INFINITY ) {
260                 char title[BCTEXTLEN];
261                 edit->get_title(title);
262                 canvas->set_color(mwindow->theme->title_color);
263                 canvas->set_font(mwindow->theme->title_font);
264
265 // Justify the text on the left boundary of the edit if it is visible.
266 // Otherwise justify it on the left side of the screen.
267                 int text_x = total_x + left_margin;
268                 text_x = MAX(left_margin, text_x);
269 //printf("ResourcePixmap::draw_title 1 %d\n", text_x);
270                 canvas->draw_text(text_x,
271                         canvas->get_text_ascent(mwindow->theme->title_font) + 2,
272                         title, strlen(title), this);
273 //      }
274 }
275
276
277 // Need to draw one more x
278 void ResourcePixmap::draw_audio_resource(TrackCanvas *canvas, Edit *edit, int x, int w)
279 {
280         if( w <= 0 ) return;
281         if( !edit->asset && !edit->nested_edl ) return;
282         Indexable *indexable = 0;
283         if( edit->asset ) indexable = edit->asset;
284         if( edit->nested_edl ) indexable = edit->nested_edl;
285 // printf("ResourcePixmap::draw_audio_resource %d x=%d w=%d\n", __LINE__, x, w);
286 SET_TRACE
287
288         IndexState *index_state = indexable->index_state;
289         double asset_over_session = (double)indexable->get_sample_rate() /
290                 mwindow->edl->session->sample_rate;
291
292 // Develop strategy for drawing
293 // printf("ResourcePixmap::draw_audio_resource %d %p %d\n",
294 // __LINE__,
295 // index_state,
296 // index_state->index_status);
297         switch( index_state->index_status )
298         {
299                 case INDEX_NOTTESTED:
300                         return;
301                         break;
302 // Disabled.  All files have an index.
303 //              case INDEX_TOOSMALL:
304 //                      draw_audio_source(canvas, edit, x, w);
305 //                      break;
306                 case INDEX_BUILDING:
307                 case INDEX_READY:
308                 {
309                         IndexFile indexfile(mwindow, indexable);
310                         if( !indexfile.open_index() ) {
311                                 if( index_state->index_zoom >
312                                                 mwindow->edl->local_session->zoom_sample *
313                                                 asset_over_session ) {
314 //printf("ResourcePixmap::draw_audio_resource %d\n", __LINE__);
315
316                                         draw_audio_source(canvas, edit, x, w);
317                                 }
318                                 else {
319 //printf("ResourcePixmap::draw_audio_resource %d\n", __LINE__);
320                                         indexfile.draw_index(canvas,
321                                                 this,
322                                                 edit,
323                                                 x,
324                                                 w);
325 SET_TRACE
326                                 }
327
328                                 indexfile.close_index();
329 SET_TRACE
330                         }
331                         break;
332                 }
333         }
334 }
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353 void ResourcePixmap::draw_audio_source(TrackCanvas *canvas, Edit *edit, int x, int w)
354 {
355         w++;
356         Indexable *indexable = edit->get_source();
357         int center_pixel = mwindow->edl->local_session->zoom_track / 2;
358         if( edit->track->show_titles() )
359                 center_pixel += mwindow->theme->get_image("title_bg_data")->get_h();
360         int64_t scale_y = mwindow->edl->local_session->zoom_y;
361         int y_max = center_pixel + scale_y / 2 - 1;
362
363         double project_zoom = mwindow->edl->local_session->zoom_sample;
364         FloatAutos *speed_autos = !edit->track->has_speed() ? 0 :
365                 (FloatAutos *)edit->track->automation->autos[AUTOMATION_SPEED];
366         int64_t edit_position = (x + pixmap_x - edit_x) * project_zoom;
367         int64_t start_position = edit->startsource;
368         start_position += !speed_autos ? edit_position :
369                 speed_autos->automation_integral(edit->startproject, edit_position, PLAY_FORWARD);
370         int64_t end_position = edit->startsource;
371         edit_position = (x + w + pixmap_x - edit_x) * project_zoom;
372         end_position += !speed_autos ? edit_position :
373                 speed_autos->automation_integral(edit->startproject, edit_position, PLAY_FORWARD);
374
375         double session_sample_rate = mwindow->edl->session->sample_rate;
376         double asset_over_session = (double)indexable->get_sample_rate() / session_sample_rate;
377         start_position *= asset_over_session;
378         end_position *= asset_over_session;
379         int sample_size = end_position - start_position;
380         if( sample_size < 0 ) sample_size = 0;
381         int source_samples = sample_size + 1;
382
383 // Single sample zoom
384         if( mwindow->edl->local_session->zoom_sample == 1 ) {
385                 Samples *buffer = 0;
386                 int result = 0;
387                 canvas->set_color(mwindow->theme->audio_color);
388
389                 if( indexable->is_asset ) {
390                         mwindow->gui->unlock_window();
391                         File *source = mwindow->audio_cache->check_out(edit->asset, mwindow->edl);
392                         mwindow->gui->lock_window("draw_audio_source");
393
394                         if( !source ) {
395                                 printf(_("ResourcePixmap::draw_audio_source: failed to check out %s for drawing.\n"), edit->asset->path);
396                                 return;
397                         }
398
399                         source->set_audio_position(start_position);
400                         source->set_channel(edit->channel);
401                         buffer = new Samples(source_samples);
402                         result = source->read_samples(buffer, source_samples);
403                         mwindow->audio_cache->check_in(edit->asset);
404                 }
405                 else {
406                         if( mwindow->gui->render_engine &&
407                                 mwindow->gui->render_engine_id != indexable->id ) {
408                                 delete mwindow->gui->render_engine;
409                                 mwindow->gui->render_engine = 0;
410                         }
411
412                         if( !mwindow->gui->render_engine ) {
413                                 TransportCommand command;
414                                 command.command = NORMAL_FWD;
415                                 command.get_edl()->copy_all(edit->nested_edl);
416                                 command.change_type = CHANGE_ALL;
417                                 command.realtime = 0;
418                                 mwindow->gui->render_engine = new RenderEngine(0,
419                                         mwindow->preferences, 0, 0);
420                                 mwindow->gui->render_engine_id = edit->nested_edl->id;
421                                 mwindow->gui->render_engine->set_acache(mwindow->audio_cache);
422                                 mwindow->gui->render_engine->arm_command(&command);
423                         }
424
425                         if( mwindow->gui->render_engine->arender ) {
426                                 Samples *buffers[MAX_CHANNELS];
427                                 memset(buffers, 0, sizeof(buffers));
428                                 int nch = indexable->get_audio_channels(), ch = edit->channel;
429                                 for( int i=0; i<nch; ++i )
430                                         buffers[i] = new Samples(source_samples);
431                                 mwindow->gui->render_engine->arender->process_buffer(
432                                         buffers, source_samples, start_position);
433                                 for( int i=0; i<nch; ++i )
434                                         if( i != ch ) delete buffers[i];
435                                 buffer = buffers[ch];
436                         }
437                 }
438
439                 if( !result ) {
440                         double *samples = buffer->get_data();
441                         int y1 = center_pixel - samples[0] * scale_y / 2;
442                         int y2 = CLIP(y1, 0, y_max);
443
444                         for( int x0=0; x0<w; ++x0 ) {
445                                 int x1 = x0 + x, x2 = x1 + 1;
446                                 edit_position = (x1 + pixmap_x - edit_x) * project_zoom;
447                                 int64_t speed_position = edit->startsource;
448                                 speed_position += !speed_autos ? edit_position :
449                                         speed_autos->automation_integral(
450                                                 edit->startproject, edit_position, PLAY_FORWARD);
451                                 int j = speed_position * asset_over_session - start_position;
452                                 CLAMP(j, 0, sample_size);
453                                 int y0 = y2;
454                                 y1 = center_pixel - samples[j] * scale_y / 2;
455                                 y2 = CLIP(y1, 0, y_max);
456 //printf("ResourcePixmap::draw_audio_source %d %d %d\n", __LINE__, y1, y2);
457                                 canvas->draw_line(x0, y0, x2, y2, this);
458                         }
459                 }
460
461                 delete buffer;
462         }
463         else {
464                 edit_position = (x + pixmap_x - edit_x) * project_zoom;
465                 int64_t speed_position = edit->startsource;
466                 speed_position += !speed_autos ? edit_position :
467                         speed_autos->automation_integral(
468                                 edit->startproject, edit_position, PLAY_FORWARD);
469                 int64_t next_position = asset_over_session * speed_position;
470 // Multiple sample zoom
471                 int first_pixel = 1, prev_y1 = -1, prev_y2 = y_max;
472                 canvas->set_color(mwindow->theme->audio_color);
473                 ++x;
474
475 // Draw each pixel from the cache
476 //printf("ResourcePixmap::draw_audio_source %d x=%d w=%d\n", __LINE__, x, w);
477                 for( int x2=x+w; x<x2; ++x ) {
478                         int64_t prev_position = next_position;
479                         edit_position = (x + pixmap_x - edit_x) * project_zoom;
480                         speed_position = edit->startsource;
481                         speed_position += !speed_autos ? edit_position :
482                                 speed_autos->automation_integral(
483                                         edit->startproject, edit_position, PLAY_FORWARD);
484                         next_position = speed_position * asset_over_session;
485 // Starting sample of pixel relative to asset rate.
486                         WaveCacheItem *item = mwindow->wave_cache->get_wave(indexable->id,
487                                         edit->channel, prev_position, next_position);
488                         if( item ) {
489 //printf("ResourcePixmap::draw_audio_source %d\n", __LINE__);
490                                 int y_lo = (int)(center_pixel - item->low * scale_y / 2);
491                                 int y1 = CLIP(y_lo, 0, y_max);
492                                 int y_hi = (int)(center_pixel - item->high * scale_y / 2);
493                                 int y2 = CLIP(y_hi, 0, y_max);
494                                 if( !first_pixel ) {
495                                         y_lo = MIN(y1,prev_y2);
496                                         y_hi = MAX(y2,prev_y1);
497                                 }
498                                 else {
499                                         first_pixel = 0;
500                                         y_lo = y1;  y_hi = y2;
501                                 }
502                                 prev_y1 = y1;  prev_y2 = y2;
503                                 canvas->draw_line(x, y_lo, x, y_hi, this);
504 //printf("ResourcePixmap::draw_audio_source %d %d %d %d\n", __LINE__, x, y1, y2);
505                                 mwindow->wave_cache->unlock();
506                         }
507                         else {
508 //printf("ResourcePixmap::draw_audio_source %d\n", __LINE__);
509                                 gui->resource_thread->add_wave(this,
510                                         canvas->pane->number, indexable, x,
511                                         edit->channel, prev_position, next_position);
512                                 first_pixel = 1;  prev_y1 = -1;  prev_y2 = y_max;
513                         }
514                 }
515         }
516
517         canvas->test_timer();
518 }
519
520 void ResourcePixmap::draw_wave(TrackCanvas *canvas,
521         int x, double high, double low)
522 {
523         int top_pixel = 0;
524         if( mwindow->edl->session->show_titles )
525                 top_pixel += mwindow->theme->get_image("title_bg_data")->get_h();
526         int center_pixel = mwindow->edl->local_session->zoom_track / 2 + top_pixel;
527         int bottom_pixel = top_pixel + mwindow->edl->local_session->zoom_track;
528         int y1 = (int)(center_pixel -
529                 low * mwindow->edl->local_session->zoom_y / 2);
530         int y2 = (int)(center_pixel -
531                 high * mwindow->edl->local_session->zoom_y / 2);
532         CLAMP(y1, top_pixel, bottom_pixel);
533         CLAMP(y2, top_pixel, bottom_pixel);
534         canvas->set_color(mwindow->theme->audio_color);
535         canvas->draw_line(x, y1, x, y2, this);
536 }
537
538
539 void ResourcePixmap::draw_video_resource(TrackCanvas *canvas,
540         Edit *edit, int64_t edit_x, int64_t edit_w, int64_t pixmap_x, int64_t pixmap_w,
541         int refresh_x, int refresh_w, int mode)
542 {
543 //PRINT_TRACE
544 //BC_Signals::dump_stack();
545
546 // pixels spanned by a picon
547         int64_t picon_w = Units::round(edit->picon_w());
548         int64_t picon_h = edit->picon_h();
549 //      if( picon_w <= 0 || picon_w > edit_w ) return;
550 // Don't draw video if picon is empty, or edit only hairline
551         if( picon_w < 1 || edit_w < 2 ) return;
552 // or bigger than edit and fills at less than 1.5 percent timeline
553         if( picon_w > edit_w && edit_w < canvas->get_w()/64 ) return;
554
555 // Frames spanned by a picon
556         double frame_w = edit->frame_w();
557 // pixels spanned by a frame
558         if( frame_w < picon_w ) frame_w = picon_w;
559 // Current pixel relative to pixmap
560         int y = 0;
561         if( edit->track->show_titles() )
562                 y += mwindow->theme->get_image("title_bg_data")->get_h();
563
564 // Frame in project touched by current pixel
565         FloatAutos *speed_autos = !edit->track->has_speed() ? 0 :
566                 (FloatAutos *)edit->track->automation->autos[AUTOMATION_SPEED];
567         Indexable *indexable = edit->get_source();
568         double session_sample_rate = mwindow->edl->session->sample_rate;
569         double project_zoom = mwindow->edl->local_session->zoom_sample / session_sample_rate;
570         int skip_frames = Units::to_int64(((int64_t)refresh_x + pixmap_x - edit_x) / frame_w);
571         int x = Units::to_int64(skip_frames * frame_w) + edit_x - pixmap_x;
572
573 // Draw only cached frames
574         while( x < refresh_x + refresh_w ) {
575                 int64_t edit_position =
576                         edit->track->to_units((x + pixmap_x - edit_x) * project_zoom, 0);
577                 int64_t speed_position = edit->startsource;
578                 speed_position += !speed_autos ? edit_position :
579                          speed_autos->automation_integral(
580                                 edit->startproject, edit_position, PLAY_FORWARD);
581                 VFrame *picon_frame = indexable->id < 0 ? 0 :
582                         mwindow->frame_cache->get_frame_ptr(speed_position, edit->channel,
583                                 mwindow->edl->session->frame_rate, BC_RGB888,
584                                 picon_w, picon_h, indexable->id);
585                 if( picon_frame ) {
586                         draw_vframe(picon_frame, x, y, picon_w, picon_h, 0, 0);
587                         mwindow->frame_cache->unlock();
588                 }
589                 else if( mode != IGNORE_THREAD ) {
590 // Set picon thread to draw in background
591 // printf("ResourcePixmap::draw_video_resource %d %d %lld\n",
592 // __LINE__, mwindow->frame_cache->total(), source_frame);
593                         gui->resource_thread->add_picon(this, canvas->pane->number, x, y,
594                                 picon_w, picon_h, mwindow->edl->session->frame_rate,
595                                 speed_position, edit->channel, indexable);
596                 }
597                 x += frame_w;
598                 canvas->test_timer();
599         }
600 }
601
602 #include "strack.h"
603
604 void ResourcePixmap::draw_subttl_resource(TrackCanvas *canvas, Edit *edit, int x, int w)
605 {
606         SEdit *sedit = (SEdit *)edit;
607         char *text = sedit->get_text();
608         if( !*text || w < 10 ) return;
609         int center_pixel = canvas->resource_h() / 2;
610         if( edit->track->show_titles() )
611                 center_pixel += mwindow->theme->get_image("title_bg_data")->get_h();
612         int64_t scale_y = mwindow->edl->local_session->zoom_y;
613         int x0 = edit_x;
614         if( x0 < 0 ) x0 = -x0;
615         int x1 = (int)(pixmap_x - x0 + x);
616         int y_max = center_pixel + scale_y / 2 - 1;
617         int font = MEDIUMFONT, color = WHITE;
618         canvas->set_font(font);
619         canvas->set_color(color);
620         int ch = canvas->get_text_height(font);
621         int hh = canvas->get_text_height(font,text) + ch/2;
622         int y1 = y_max - hh - 10;
623         if( y1 < 0 ) y1 = 0;
624         canvas->draw_text(x1, y1, text, -1, this);
625 }
626
627 void ResourcePixmap::dump()
628 {
629         printf("ResourcePixmap %p\n", this);
630         printf(" edit %jx edit_x %jd pixmap_x %jd pixmap_w %jd visible %d\n",
631                 edit_id, edit_x, pixmap_x, pixmap_w, visible);
632 }
633