Ejemplo n.º 1
0
void ItemView::drawReminderIcon(const Cairo::RefPtr<Cairo::Context>& cr, const int width, const int height)
{
    cr->save();

    //draw reminder icon
    cr->set_antialias(Cairo::ANTIALIAS_NONE);

    if (data.isReminder())
    {
        Gtk::Image* image = Resources::res->imgReminderIcon;

        if (getColorMode() == COLOR_ALARM)
            image = Resources::res->imgReminderOnIcon;

        const Glib::RefPtr<Gdk::Pixbuf> icon = image->get_pixbuf();

        const int iconLeft = (TIME_WIDTH * 0.5) - (icon->get_width() * 0.5);
        const int iconTop = (height - icon->get_height()) - (PADDING * 3);

        Gdk::Cairo::set_source_pixbuf(cr, icon, iconLeft, iconTop);

        cr->rectangle(iconLeft, iconTop, icon->get_width(), icon->get_height());
        cr->fill();
    }

    cr->restore();
}
Ejemplo n.º 2
0
void
Renderer_Dragbox::render_vfunc(
	const Glib::RefPtr<Gdk::Window>& drawable,
	const Gdk::Rectangle& /*expose_area*/
)
{
	assert(get_work_area());
	if(!get_work_area())
		return;

	// const synfig::Vector focus_point(get_work_area()->get_focus_point());
	// Warning : Unused focus_point
	int drawable_w = drawable->get_width();
	int drawable_h = drawable->get_height();

	Cairo::RefPtr<Cairo::Context> cr = drawable->create_cairo_context();

	const synfig::Vector::value_type window_startx(get_work_area()->get_window_tl()[0]);
	const synfig::Vector::value_type window_starty(get_work_area()->get_window_tl()[1]);
	const float pw(get_pw()),ph(get_ph());

	const synfig::Point& curr_point(get_curr_point());
	const synfig::Point& drag_point(get_drag_point());

	{
		cr->save();
		cr->set_line_cap(Cairo::LINE_CAP_BUTT);
		cr->set_line_join(Cairo::LINE_JOIN_MITER);
		cr->set_antialias(Cairo::ANTIALIAS_NONE);

		cr->set_line_width(1.0);
		cr->set_source_rgb(0,0,0);
		std::valarray<double> dashes(2);
		dashes[0]=5.0;
		dashes[1]=5.0;
		cr->set_dash(dashes, 0);

		Point tl(std::min(drag_point[0],curr_point[0]),std::min(drag_point[1],curr_point[1]));
		Point br(std::max(drag_point[0],curr_point[0]),std::max(drag_point[1],curr_point[1]));

		tl[0]=(tl[0]-window_startx)/pw;
		tl[1]=(tl[1]-window_starty)/ph;
		br[0]=(br[0]-window_startx)/pw;
		br[1]=(br[1]-window_starty)/ph;
		if(tl[0]>br[0])
			swap(tl[0],br[0]);
		if(tl[1]>br[1])
			swap(tl[1],br[1]);

		cr->rectangle(
			tl[0],
			tl[1],
			br[0]-tl[0],
			br[1]-tl[1]
		);
		cr->stroke();

		cr->restore();
	}
}
Ejemplo n.º 3
0
bool ItemView::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
    Gtk::Allocation allocation = get_allocation();

    int width = allocation.get_width();
    int height = allocation.get_height();

    //draw bottom shadow
    cr->set_source_rgb(0.9, 0.9, 0.9);
    cr->paint();

    //make room for content
    height -= 1;

    //update clear notification button layout
    updateClearNotificationButtonLayout(width, height);

    fontTime.set_size(FONT_SIZE * PANGO_SCALE);
    fontTitle.set_size(FONT_SIZE * PANGO_SCALE);
    fontDescription.set_size(FONT_SIZE_SMALL * PANGO_SCALE);

    cr->set_antialias(Cairo::ANTIALIAS_NONE);

    drawBackground(cr, width, height);

    cr->set_antialias(Cairo::ANTIALIAS_DEFAULT);

    //draw objects
    drawTime(cr, width, height);
    drawTitle(cr, width, height);
    drawDescription(cr, width, height);
    drawReminderIcon(cr, width, height);

    //update buttons layout according to selection state and description position
    updateButtonsLayout(width, height, rectDescription.get_y(), rectDescription.get_height());

    //draw buttons
    drawButtons(cr, width, height);

    return true;
}
Ejemplo n.º 4
0
void ItemView::drawButtons(const Cairo::RefPtr<Cairo::Context>& cr, const int width, const int height)
{
    cr->save();

    cr->set_antialias(Cairo::ANTIALIAS_NONE);

    if (isSelected())
    {
        drawButton(cr, Resources::res->imgBtnDelete, rectBtnDelete);
        drawButton(cr, Resources::res->imgBtnEdit, rectBtnEdit);
    }

    cr->restore();
}
Ejemplo n.º 5
0
bool rasterpolys(const vector<Poly> &polys,
		 const Vector2d &min, const Vector2d &max, double resolution,
		 Cairo::RefPtr<Cairo::ImageSurface> &surface,
		 Cairo::RefPtr<Cairo::Context> &context)
{
  Vector2d diag = max - min;
  int width  = (int)ceil(diag.x()/resolution);
  int height = (int)ceil(diag.y()/resolution);
  if (height <= 0 || width <= 0)
    return false;
  surface = Cairo::ImageSurface::create(Cairo::FORMAT_A8, width, height);
  //surface->set_device_offset(-min.x()/resolution, -min.y()/resolution);
  context = Cairo::Context::create (surface);
  context->set_fill_rule(Cairo::FILL_RULE_WINDING);
  context->set_antialias(Cairo::ANTIALIAS_DEFAULT);
  context->scale(1/resolution, 1/resolution);
  context->translate(-min.x(), -min.y());
  context->set_source_rgb (0,0,0);
  //cerr << min << endl <<getMatrix(context) << endl;

  // draw boundary
  // context->begin_new_path();
  // context->set_line_width(0.5);
  // context->move_to(min.x(),min.y());
  // context->line_to(max.x(),min.y());
  // context->line_to(max.x(),max.y());
  // context->line_to(min.x(),max.y());
  // // context->move_to(0,0);
  // // context->line_to(diag.x(),0);
  // // context->line_to(diag.x(),diag.y());
  // // context->line_to(0,diag.y());
  // context->close_path();
  // context->stroke();

  context->begin_new_path();
  context->set_line_width(0);
  for (uint i=0; i<polys.size(); i++) {
    Vector2d v = polys[i][0];
    context->move_to(v.x(),v.y());
    for (uint j=0; j<polys[i].size(); j++) {
      Vector2d v = polys[i][j];
      context->line_to(v.x(),v.y());
    }
  }
  context->fill();
  return true;
}
Ejemplo n.º 6
0
void ItemView::drawInnerShadow(const Cairo::RefPtr<Cairo::Context>& cr, const int width, const int height)
{
    cr->set_antialias(Cairo::ANTIALIAS_DEFAULT);

    const int SIZE = height * 0.1;
    const double ALPHA = 0.2;
    const int x = TIME_WIDTH - SIZE;
    const int y = 0;

    Cairo::RefPtr<Cairo::LinearGradient> linearGradient = Cairo::LinearGradient::create(x, y, x + SIZE, y);
    linearGradient->add_color_stop_rgba(0, 0.00, 0.00, 0.00, 0.0);
    linearGradient->add_color_stop_rgba(1, 0.00, 0.00, 0.00, ALPHA);

    cr->set_source(linearGradient);
    cr->rectangle(x, y, SIZE, height);
    cr->fill();
}
Ejemplo n.º 7
0
void Mediator::redraw()
{
  Glib::RefPtr<Gdk::Window> Window = mref_DrawingArea.get_window();

  if (Window)
  {
    Window->clear();

    if (!m_Layers.empty())
    {
      Cairo::RefPtr<Cairo::Context> Context = Window->create_cairo_context();
      Gtk::Allocation allocation = mref_DrawingArea.get_allocation();
      const int width = allocation.get_width();
      const int height = allocation.get_height();

      Context->rectangle(0, 0, width, height);
      Context->clip();
      Context->set_antialias(Cairo::ANTIALIAS_SUBPIXEL);
      Context->scale(mref_DrawingArea.getScale(), -mref_DrawingArea.getScale());
      Context->translate(-mref_DrawingArea.getXTranslate(),
          -mref_DrawingArea.getYTranslate());
      std::vector<Layer*>::reverse_iterator rit;
      for (rit = m_Layers.rbegin(); rit < m_Layers.rend(); ++rit)
      {
        if ((*rit)->getIsDisplay())
        {
          (*rit)->initialiseLayerContext(Context, mref_DrawingArea.getScale());
          if ((*rit)->getClassName() == m_SelectedClassName)
          {
            (*rit)->draw(Context, mref_DrawingArea.getScale(),
                m_SelectedUnitIds, (*rit)->getDisplayID());
          }
          else
          {
            std::set<int> tempVoidVector;
            (*rit)->draw(Context, mref_DrawingArea.getScale(), tempVoidVector,
                (*rit)->getDisplayID());
          }
        }
      }
    }
  }
}
Ejemplo n.º 8
0
void
Renderer_Grid::render_vfunc(
	const Glib::RefPtr<Gdk::Window>& drawable,
	const Gdk::Rectangle& /*expose_area*/
)
{
	assert(get_work_area());
	if(!get_work_area())
		return;

	Cairo::RefPtr<Cairo::Context> cr = drawable->create_cairo_context();

	int drawable_w = drawable->get_width();
	int drawable_h = drawable->get_height();

	synfig::Vector grid_size(get_grid_size());
	if(grid_size[0] < 0) grid_size[0] = -grid_size[0];
	if(grid_size[1] < 0) grid_size[1] = -grid_size[1];

	const synfig::Vector::value_type window_startx(get_work_area()->get_window_tl()[0]);
	const synfig::Vector::value_type window_endx(get_work_area()->get_window_br()[0]);
	const synfig::Vector::value_type window_starty(get_work_area()->get_window_tl()[1]);
	const synfig::Vector::value_type window_endy(get_work_area()->get_window_br()[1]);
	const float pw(get_pw()),ph(get_ph());
	
	synfig::Color grid_color(get_work_area()->get_grid_color());

	// Draw out the grid
	if(grid_size[0]>pw*3.5 && grid_size[1]>ph*3.5)
	{
		synfig::Vector::value_type x,y;

		x=floor(window_startx/grid_size[0])*grid_size[0];
		y=floor(window_starty/grid_size[1])*grid_size[1];

		cr->save();
		cr->set_line_cap(Cairo::LINE_CAP_BUTT);
		cr->set_line_join(Cairo::LINE_JOIN_MITER);
		cr->set_antialias(Cairo::ANTIALIAS_NONE);

		cr->set_line_width(1.0);
		cr->set_source_rgb(grid_color.get_r(),grid_color.get_g(),grid_color.get_b()); 
		std::valarray<double> dashes(2);
		dashes[0]=4.0;
		dashes[1]=4.0;
		cr->set_dash(dashes, 0);

		if(x<window_endx)
			for(;x<window_endx;x+=grid_size[0])
			{
				cr->move_to(
					round_to_int((x-window_startx)/pw),
					0
					);
				cr->line_to(
					round_to_int((x-window_startx)/pw),
					drawable_h
				);
				cr->stroke();
			}
		else
			for(;x>window_endx;x-=grid_size[0])
			{
				cr->move_to(
					round_to_int((x-window_startx)/pw),
					0
					);
				cr->line_to(
					round_to_int((x-window_startx)/pw),
					drawable_h
				);
				cr->stroke();
			}

		if(y<window_endy)
			for(;y<window_endy;y+=grid_size[1])
			{
				cr->move_to(
					0,
					round_to_int((y-window_starty)/ph)
					);
				cr->line_to(
					drawable_w,
					round_to_int((y-window_starty)/ph)
				);
				cr->stroke();
			}
		else
			for(;y>window_endy;y-=grid_size[1])
			{
				cr->move_to(
					0,
					round_to_int((y-window_starty)/ph)
					);
				cr->line_to(
					drawable_w,
					round_to_int((y-window_starty)/ph)
				);
				cr->stroke();
			}
		cr->restore();
	}
}
Ejemplo n.º 9
0
void
Renderer_Guides::render_vfunc(
	const Glib::RefPtr<Gdk::Drawable>& drawable,
	const Gdk::Rectangle& /*expose_area*/
)
{
	assert(get_work_area());
	if(!get_work_area())
		return;


	int drawable_w,drawable_h;
	drawable->get_size(drawable_w,drawable_h);

	Cairo::RefPtr<Cairo::Context> cr = drawable->create_cairo_context();

	const synfig::Vector::value_type window_startx(get_work_area()->get_window_tl()[0]);
	const synfig::Vector::value_type window_starty(get_work_area()->get_window_tl()[1]);
	const float pw(get_pw()),ph(get_ph());

	// Draw out the guides
	{
		Duckmatic::GuideList::const_iterator iter;

		cr->save();
		cr->set_line_cap(Cairo::LINE_CAP_BUTT);
		cr->set_line_join(Cairo::LINE_JOIN_MITER);
		cr->set_antialias(Cairo::ANTIALIAS_NONE);

		cr->set_line_width(1.0);
		std::valarray<double> dashes(2);
		dashes[0]=5.0;
		dashes[1]=5.0;
		cr->set_dash(dashes, 0);

		// vertical
		for(iter=get_guide_list_x().begin();iter!=get_guide_list_x().end();++iter)
		{
			const float x((*iter-window_startx)/pw);

			if(iter==get_work_area()->curr_guide)
				cr->set_source_rgb(1.0,111.0/255.0,111.0/255.0);
			else
				cr->set_source_rgb(111.0/255.0,111.0/255.0,1.0);

			cr->move_to(
				x,
				0
				);
			cr->line_to(
				x,
				drawable_h
			);
			cr->stroke();
		}
		// horizontal
		for(iter=get_guide_list_y().begin();iter!=get_guide_list_y().end();++iter)
		{
			const float y((*iter-window_starty)/ph);

			if(iter==get_work_area()->curr_guide)
				cr->set_source_rgb(1.0,111.0/255.0,111.0/255.0);
			else
				cr->set_source_rgb(111.0/255.0,111.0/255.0,1.0);

			cr->move_to(
				0,
				y
				);
			cr->line_to(
				drawable_w,
				y
			);
			cr->stroke();
		}

		cr->restore();
	}
}
Ejemplo n.º 10
0
bool studio::Widget_NavView::on_expose_draw(GdkEventExpose */*exp*/)
{
#ifdef SINGLE_THREADED
	// don't redraw if the previous redraw is still running single-threaded
	// or we end up destroying the renderer that's rendering it
	if (App::single_threaded && renderer && renderer->updating)
		return false;
#endif

	//print out the zoom
	//HACK kind of...
	//zoom_print.set_text(strprintf("%.1f%%",100*unit_to_zoom(adj_zoom.get_value())));

	//draw the good stuff
	on_start_render();

	//if we've got a preview etc. display it...
	if(get_canvas_view() && prev)
	{
		//axis transform from units to pixel coords
		float xaxis = 0, yaxis = 0;

		int canvw = get_canvas_view()->get_canvas()->rend_desc().get_w();
		//int canvh = get_canvas_view()->get_canvas()->rend_desc().get_h();

		float pw = get_canvas_view()->get_canvas()->rend_desc().get_pw();
		float ph = get_canvas_view()->get_canvas()->rend_desc().get_ph();

		int w = prev->get_width();
		int h = prev->get_height();

		//scale up/down to the nearest pixel ratio...
		//and center in center
		int offx=0, offy=0;

		float sx, sy;
		int nw,nh;

		sx = drawto.get_width() / (float)w;
		sy = drawto.get_height() / (float)h;

		//synfig::warning("Nav redraw: now to scale the bitmap: %.3f x %.3f",sx,sy);

		//round to smallest scale (fit entire thing in window without distortion)
		if(sx > sy) sx = sy;
		//else sy = sx;

		//scaling and stuff
		// the point to navpixel space conversion should be:
		//		(navpixels / canvpixels) * (canvpixels / canvsize)
		//	or (navpixels / prevpixels) * (prevpixels / navpixels)
		xaxis = sx * w / (float)canvw;
		yaxis = xaxis/ph;
		xaxis /= pw;

		//scale to a new pixmap and then copy over to the window
		nw = (int)(w*sx);
		nh = (int)(h*sx);

		//must now center to be cool
		offx = (drawto.get_width() - nw)/2;
		offy = (drawto.get_height() - nh)/2;

		//trivial escape
		if(nw == 0 || nh == 0)return true;

		//draw to drawing area
		Glib::RefPtr<Gdk::GC>	gc = Gdk::GC::create(drawto.get_window());
		Cairo::RefPtr<Cairo::Context> cr = drawto.get_window()->create_cairo_context();

		//synfig::warning("Nav: Scaling pixmap to off (%d,%d) with size (%d,%d)", offx,offy,nw, nh);
		Glib::RefPtr<Gdk::Pixbuf> scalepx = prev->scale_simple(nw,nh,Gdk::INTERP_NEAREST);

		cr->save();

		//synfig::warning("Nav: Drawing scaled bitmap");
		Gdk::Cairo::set_source_pixbuf(
			cr, //cairo context
			scalepx, //pixbuf
			offx, offy //coordinates to place upper left corner of pixbuf
			);
		cr->paint();

		//draw fancy red rectangle around focus point
		const Point &wtl = get_canvas_view()->work_area->get_window_tl(),
					&wbr = get_canvas_view()->work_area->get_window_br();

		//it must be clamped to the drawing area though
		int l=0,rw=0,t=0,rh=0;
		const Point fp = -get_canvas_view()->work_area->get_focus_point();

		//get focus point in normal space
		rw = (int)(abs((wtl[0]-wbr[0])*xaxis));
		rh = (int)(abs((wtl[1]-wbr[1])*yaxis));

		//transform into pixel space
		l = (int)(drawto.get_width()/2 + fp[0]*xaxis - rw/2);
		t = (int)(drawto.get_height()/2 + fp[1]*yaxis - rh/2);

		//coord system:
		// tl : (offx,offy)
		// axis multipliers = xaxis,yaxis
		//synfig::warning("Nav: tl (%f,%f), br (%f,%f)", wtl[0],wtl[1],wbr[0],wbr[1]);
		//synfig::warning("Nav: tl (%f,%f), br (%f,%f)", wtl[0],wtl[1],wbr[0],wbr[1]);
		//synfig::warning("Nav: Drawing Rectangle (%d,%d) with dim (%d,%d)", l,t,rw,rh);

		cr->set_line_width(2.0);
		cr->set_line_cap(Cairo::LINE_CAP_BUTT);
		cr->set_line_join(Cairo::LINE_JOIN_MITER);
		cr->set_antialias(Cairo::ANTIALIAS_NONE);
		cr->set_source_rgb(1,0,0);
		cr->rectangle(l,t,rw,rh);
		cr->stroke();

		cr->restore();
	}

	return false; //draw everything else too
}
Ejemplo n.º 11
0
bool studio::Widget_NavView::on_drawto_draw(const Cairo::RefPtr<Cairo::Context> &cr)
{
#ifdef SINGLE_THREADED
	// don't redraw if the previous redraw is still running single-threaded
	// or we end up destroying the renderer that's rendering it
	if (App::single_threaded && renderer && renderer->updating)
		return false;
#endif

	//draw the good stuff
	on_start_render();

	//if we've got a preview etc. display it...
	if(get_canvas_view())
	{
		//axis transform from units to pixel coords
		float xaxis = 0, yaxis = 0;

		int canvw = get_canvas_view()->get_canvas()->rend_desc().get_w();
		int w, h;
	
		float pw = get_canvas_view()->get_canvas()->rend_desc().get_pw();
		float ph = get_canvas_view()->get_canvas()->rend_desc().get_ph();
		if(prev && !studio::App::navigator_uses_cairo)
		{
			w = prev->get_width();
			h = prev->get_height();
		}
		if(studio::App::navigator_uses_cairo)
		{
			w=cairo_image_surface_get_width(cairo_surface);
			h=cairo_image_surface_get_height(cairo_surface);
		}

		//scale up/down to the nearest pixel ratio...
		//and center in center
		float offx=0, offy=0;

		float sx, sy;
		int nw,nh;

		sx = drawto.get_width() / (float)w;
		sy = drawto.get_height() / (float)h;

		//round to smallest scale (fit entire thing in window without distortion)
		if(sx > sy) sx = sy;
		//else sy = sx;

		//scaling and stuff
		// the point to navpixel space conversion should be:
		//		(navpixels / canvpixels) * (canvpixels / canvsize)
		//	or (navpixels / prevpixels) * (prevpixels / navpixels)
		xaxis = sx * w / (float)canvw;
		yaxis = xaxis/ph;
		xaxis /= pw;

		//scale to a new pixmap and then copy over to the window
		nw = (int)(w*sx);
		nh = (int)(h*sx);

		//must now center to be cool
		offx = (drawto.get_width() - nw)/2;
		offy = (drawto.get_height() - nh)/2;

		//trivial escape
		if(nw == 0 || nh == 0)return true;

		//draw to drawing area
		if(prev && !studio::App::navigator_uses_cairo)
		{
			Glib::RefPtr<Gdk::Pixbuf> scalepx = prev->scale_simple(nw,nh,Gdk::INTERP_NEAREST);

			cr->save();

			//synfig::warning("Nav: Drawing scaled bitmap");
			Gdk::Cairo::set_source_pixbuf(
				cr, //cairo context
				scalepx, //pixbuf
				(int)offx, (int)offy //coordinates to place upper left corner of pixbuf
				);
			cr->paint();
			cr->restore();
		}
		if(studio::App::navigator_uses_cairo)
		{
			cr->save();
			cr->scale(sx, sx);
			cairo_set_source_surface(cr->cobj(), cairo_surface, offx/sx, offy/sx);
			cairo_pattern_set_filter(cairo_get_source(cr->cobj()), CAIRO_FILTER_NEAREST);
			cr->paint();
			cr->restore();	
		}
		cr->save();
		//draw fancy red rectangle around focus point
		const Point &wtl = get_canvas_view()->work_area->get_window_tl(),
					&wbr = get_canvas_view()->work_area->get_window_br();

		//it must be clamped to the drawing area though
		int l=0,rw=0,t=0,rh=0;
		const Point fp = -get_canvas_view()->work_area->get_focus_point();

		//get focus point in normal space
		rw = (int)(abs((wtl[0]-wbr[0])*xaxis));
		rh = (int)(abs((wtl[1]-wbr[1])*yaxis));

		//transform into pixel space
		l = (int)(drawto.get_width()/2 + fp[0]*xaxis - rw/2);
		t = (int)(drawto.get_height()/2 + fp[1]*yaxis - rh/2);

		//coord system:
		// tl : (offx,offy)
		// axis multipliers = xaxis,yaxis

		cr->set_line_width(2.0);
		cr->set_line_cap(Cairo::LINE_CAP_BUTT);
		cr->set_line_join(Cairo::LINE_JOIN_MITER);
		cr->set_antialias(Cairo::ANTIALIAS_NONE);
		// Visually distinguish when using Cairo on Navigator or not.
		if(!studio::App::navigator_uses_cairo)
			cr->set_source_rgb(1,0,0);
		else
			cr->set_source_rgb(0,1,0);
		cr->rectangle(l,t,rw,rh);
		cr->stroke();

		cr->restore();
	}
	return false; //draw everything else too
}
Ejemplo n.º 12
0
bool TimeLine::on_draw(Cairo::RefPtr<Cairo::Context> const& cr)
{
    if(!m_mainWindow->IsFileOpened())
    {
        return false;
    }

    cr->save();
    cr->set_antialias(Cairo::ANTIALIAS_NONE);

    Gtk::Allocation allocation = get_allocation();

    cr->set_source_rgb(1.0, 1.0, 1.0);
    cr->rectangle(0.0, 0.0, allocation.get_width(), allocation.get_height());
    cr->fill();

    cr->set_line_width(1.0);
    cr->set_source_rgb(0.0, 0.0, 0.0);
    cr->move_to(0.0, 1.0);
    cr->line_to(allocation.get_width(), 1.0);
    cr->stroke();
    cr->move_to(0.0, allocation.get_height() - 1);
    cr->line_to(allocation.get_width(), allocation.get_height());
    cr->stroke();

    double floorStart = (floor(m_timeStart) - m_timeStart) * m_mainWindow->GetTimeScale();
    int numTicks = ceil(allocation.get_width() / m_mainWindow->GetTimeScale());
    for(int i = 0; i <= numTicks; ++i)
    {
        double x = floorStart + i * m_mainWindow->GetTimeScale();

        if(m_timeStart != 0.0 || i != 0)
        {
            // Get the text dimensions.
            int textWidth;
            int textHeight;
            char timeStr[10];
            sprintf(timeStr, "%d s", int(floor(m_timeStart) + i));
            m_layout->set_text(timeStr);
            m_layout->get_pixel_size(textWidth, textHeight);

            // Position the text in the middle
            cr->move_to(x - textWidth / 2, 0.0);
            m_layout->show_in_cairo_context(cr);

            // Draw tick.
            cr->move_to(x, allocation.get_height() - 8.0);
            cr->line_to(x, allocation.get_height());
            cr->stroke();
        }

        if(i < numTicks)
        {
            // Draw sub-tick.
            double nextX = floorStart + (i + 1) * m_mainWindow->GetTimeScale();
            double tickWidth = nextX - x;

            if(tickWidth > 200.0)
            {
                // Get the text dimensions.
                int textWidth;
                int textHeight;
                char timeStr[10];
                sprintf(timeStr, "%d.5 s", int(floor(m_timeStart) + i));
                m_layout->set_text(timeStr);
                m_layout->get_pixel_size(textWidth, textHeight);

                // Position the text in the middle
                cr->move_to(x + (tickWidth - textWidth) / 2, 0.0);
                m_layout->show_in_cairo_context(cr);
            }

            cr->move_to(x + tickWidth / 2, allocation.get_height() - 4.0);
            cr->line_to(x + tickWidth / 2, allocation.get_height());
            cr->stroke();
        }
    }

    cr->restore();

    return true;
}