/*
 * ***** BEGIN GPL LICENSE BLOCK *****
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * The Original Code is Copyright (C) 2011 Blender Foundation.
 * All rights reserved.
 *
 *
 * Contributor(s): Blender Foundation,
 *                 Sergey Sharybin
 *
 * ***** END GPL LICENSE BLOCK *****
 */

/** \file blender/editors/space_clip/clip_draw.c
 *  \ingroup spclip
 */

#include "DNA_gpencil_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"  /* SELECT */
#include "DNA_mask_types.h"

#include "MEM_guardedalloc.h"

#include "BKE_context.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
#include "BKE_mask.h"

#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"

#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_rect.h"
#include "BLI_math_base.h"

#include "ED_screen.h"
#include "ED_clip.h"
#include "ED_mask.h"
#include "ED_gpencil.h"

#include "BIF_gl.h"
#include "BIF_glutil.h"

#include "WM_api.h"
#include "WM_types.h"

#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"

#include "RNA_access.h"

#include "BLF_api.h"

#include "clip_intern.h"    // own include

/*********************** main area drawing *************************/

void clip_draw_curfra_label(const int framenr, const float x, const float y)
{
	uiStyle *style = UI_GetStyle();
	int fontid = style->widget.uifont_id;
	char numstr[32];
	float font_dims[2] = {0.0f, 0.0f};

	/* frame number */
	BLF_size(fontid, 11.0f, U.dpi);
	BLI_snprintf(numstr, sizeof(numstr), "%d", framenr);

	BLF_width_and_height(fontid, numstr, &font_dims[0], &font_dims[1]);

	glRecti(x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f);

	UI_ThemeColor(TH_TEXT);
	BLF_position(fontid, x + 2.0f, y + 2.0f, 0.0f);
	BLF_draw(fontid, numstr, sizeof(numstr));
}

static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int width)
{
	int height = (frame == cfra) ? 22 : 10;
	int x = (frame - sfra) * framelen;

	if (width == 1) {
		glBegin(GL_LINES);
		glVertex2i(x, 0);
		glVertex2i(x, height * UI_DPI_FAC);
		glEnd();
	}
	else {
		glRecti(x, 0, x + width, height * UI_DPI_FAC);
	}
}

static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Scene *scene)
{
	float x;
	int *points, totseg, i, a;
	float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
	MovieTracking *tracking = &clip->tracking;
	MovieTrackingObject *act_object = BKE_tracking_object_get_active(tracking);
	MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
	MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);

	glEnable(GL_BLEND);

	/* cache background */
	glColor4ub(128, 128, 255, 64);
	glRecti(0, 0, ar->winx, 8 * UI_DPI_FAC);

	/* cached segments -- could be usefu lto debug caching strategies */
	BKE_movieclip_get_cache_segments(clip, &sc->user, &totseg, &points);
	if (totseg) {
		glColor4ub(128, 128, 255, 128);

		for (a = 0; a < totseg; a++) {
			float x1, x2;

			x1 = (points[a * 2] - sfra) / (efra - sfra + 1) * ar->winx;
			x2 = (points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * ar->winx;

			glRecti(x1, 0, x2, 8 * UI_DPI_FAC);
		}
	}

	/* track */
	if (act_track) {
		MovieTrackingTrack *track = act_track;

		for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) {
			int framenr;
			MovieTrackingMarker *marker;

			while (a < track->markersnr) {
				if (track->markers[a].framenr >= i)
					break;

				if (a < track->markersnr - 1 && track->markers[a + 1].framenr > i)
					break;

				a++;
			}

			if (a < track->markersnr)
				marker = &track->markers[a];
			else
				marker = &track->markers[track->markersnr - 1];

			if ((marker->flag & MARKER_DISABLED) == 0) {
				framenr = marker->framenr;

				if (framenr != i)
					glColor4ub(128, 128, 0, 96);
				else if ((marker->flag & MARKER_TRACKED) == 0)
					glColor4ub(255, 255, 0, 196);
				else
					glColor4ub(255, 255, 0, 96);

				glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4 * UI_DPI_FAC);
			}
		}
	}

	/* failed frames */
	if (reconstruction->flag & TRACKING_RECONSTRUCTED) {
		int n = reconstruction->camnr;
		MovieReconstructedCamera *cameras = reconstruction->cameras;

		glColor4ub(255, 0, 0, 96);

		for (i = sfra, a = 0; i <= efra; i++) {
			int ok = FALSE;

			while (a < n) {
				if (cameras[a].framenr == i) {
					ok = TRUE;
					break;
				}
				else if (cameras[a].framenr > i) {
					break;
				}

				a++;
			}

			if (!ok)
				glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8 * UI_DPI_FAC);
		}
	}

	glDisable(GL_BLEND);

	/* current frame */
	x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx;

	UI_ThemeColor(TH_CFRAME);
	glRecti(x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);

	clip_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC);

	/* solver keyframes */
	glColor4ub(175, 255, 0, 255);
	draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2);
	draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2);

	/* movie clip animation */
	if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask_info.mask) {
		ED_mask_draw_frames(sc->mask_info.mask, ar, CFRA, sfra, efra);
	}
}

static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
{
	MovieClip *clip = ED_space_clip_get_clip(sc);
	MovieTracking *tracking = &clip->tracking;
	char str[256] = {0};
	int block = FALSE;

	if (tracking->stats) {
		BLI_strncpy(str, tracking->stats->message, sizeof(str));
		block = TRUE;
	}
	else {
		if (sc->flag & SC_LOCK_SELECTION)
			strcpy(str, "Locked");
	}

	if (str[0])
		ED_region_info_draw(ar, str, block, 0.6f);
}

static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
                                  int width, int height, float zoomx, float zoomy)
{
	int x, y;

	/* find window pixel coordinates of origin */
	UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);

	if (sc->flag & SC_MUTE_FOOTAGE) {
		glColor3f(0.0f, 0.0f, 0.0f);
		glRectf(x, y, x + zoomx * width, y + zoomy * height);
	}
	else {
		unsigned char *display_buffer;
		void *cache_handle;

		display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);

		if (display_buffer) {
			int need_fallback = 1;

			if (ED_space_clip_texture_buffer_supported(sc)) {
				if (ED_space_clip_load_movieclip_buffer(sc, ibuf, display_buffer)) {
					glPushMatrix();
					glTranslatef(x, y, 0.0f);
					glScalef(zoomx, zoomy, 1.0f);

					glBegin(GL_QUADS);
					glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f,  0.0f);
					glTexCoord2f(1.0f, 0.0f); glVertex2f(width, 0.0f);
					glTexCoord2f(1.0f, 1.0f); glVertex2f(width, height);
					glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f,  height);
					glEnd();

					glPopMatrix();

					ED_space_clip_unload_movieclip_buffer(sc);

					need_fallback = 0;
				}
			}

			/* if texture buffers aren't efficiently supported or texture is too large to
			 * be binder fallback to simple draw pixels solution */
			if (need_fallback) {
				/* set zoom */
				glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);

				glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);

				/* reset zoom */
				glPixelZoom(1.0f, 1.0f);
			}
		}

		IMB_display_buffer_release(cache_handle);
	}
}

static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy)
{
	int x, y;
	MovieClip *clip = ED_space_clip_get_clip(sc);

	/* find window pixel coordinates of origin */
	UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);

	/* draw boundary border for frame if stabilization is enabled */
	if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
		glColor3f(0.0f, 0.0f, 0.0f);
		glLineStipple(3, 0xaaaa);
		glEnable(GL_LINE_STIPPLE);
		glEnable(GL_COLOR_LOGIC_OP);
		glLogicOp(GL_NOR);

		glPushMatrix();
		glTranslatef(x, y, 0.0f);

		glScalef(zoomx, zoomy, 1.0f);
		glMultMatrixf(sc->stabmat);

		glBegin(GL_LINE_LOOP);
		glVertex2f(0.0f, 0.0f);
		glVertex2f(width, 0.0f);
		glVertex2f(width, height);
		glVertex2f(0.0f, height);
		glEnd();

		glPopMatrix();

		glDisable(GL_COLOR_LOGIC_OP);
		glDisable(GL_LINE_STIPPLE);
	}
}

static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackingTrack *track)
{
	int count = sc->path_length;
	int i, a, b, curindex = -1;
	float path[102][2];
	int tiny = sc->flag & SC_SHOW_TINY_MARKER, framenr, start_frame;
	MovieTrackingMarker *marker;

	if (count == 0)
		return;

	start_frame = framenr = ED_space_clip_get_clip_frame_number(sc);

	marker = BKE_tracking_marker_get(track, framenr);
	if (marker->framenr != framenr || marker->flag & MARKER_DISABLED)
		return;

	a = count;
	i = framenr - 1;
	while (i >= framenr - count) {
		marker = BKE_tracking_marker_get(track, i);

		if (!marker || marker->flag & MARKER_DISABLED)
			break;

		if (marker->framenr == i) {
			add_v2_v2v2(path[--a], marker->pos, track->offset);
			ED_clip_point_undistorted_pos(sc, path[a], path[a]);

			if (marker->framenr == start_frame)
				curindex = a;
		}
		else {
			break;
		}

		i--;
	}

	b = count;
	i = framenr;
	while (i <= framenr + count) {
		marker = BKE_tracking_marker_get(track, i);

		if (!marker || marker->flag & MARKER_DISABLED)
			break;

		if (marker->framenr == i) {
			if (marker->framenr == start_frame)
				curindex = b;

			add_v2_v2v2(path[b++], marker->pos, track->offset);
			ED_clip_point_undistorted_pos(sc, path[b - 1], path[b - 1]);
		}
		else
			break;

		i++;
	}

	if (!tiny) {
		UI_ThemeColor(TH_MARKER_OUTLINE);

		if (TRACK_VIEW_SELECTED(sc, track)) {
			glPointSize(5.0f);
			glBegin(GL_POINTS);
			for (i = a; i < b; i++) {
				if (i != curindex)
					glVertex2f(path[i][0], path[i][1]);
			}
			glEnd();
		}

		glLineWidth(3.0f);
		glBegin(GL_LINE_STRIP);
		for (i = a; i < b; i++)
			glVertex2f(path[i][0], path[i][1]);
		glEnd();
		glLineWidth(1.0f);
	}

	UI_ThemeColor(TH_PATH_BEFORE);

	if (TRACK_VIEW_SELECTED(sc, track)) {
		glPointSize(3.0f);
		glBegin(GL_POINTS);
		for (i = a; i < b; i++) {
			if (i == count + 1)
				UI_ThemeColor(TH_PATH_AFTER);

			if (i != curindex)
				glVertex2f(path[i][0], path[i][1]);
		}
		glEnd();
	}

	UI_ThemeColor(TH_PATH_BEFORE);

	glBegin(GL_LINE_STRIP);
	for (i = a; i < b; i++) {
		if (i == count + 1)
			UI_ThemeColor(TH_PATH_AFTER);

		glVertex2f(path[i][0], path[i][1]);
	}
	glEnd();
	glPointSize(1.0f);
}

static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
                                float marker_pos[2], int width, int height)
{
	int tiny = sc->flag & SC_SHOW_TINY_MARKER;
	int show_search = FALSE;
	float px[2];

	UI_ThemeColor(TH_MARKER_OUTLINE);

	px[0] = 1.0f / width / sc->zoom;
	px[1] = 1.0f / height / sc->zoom;

	if ((marker->flag & MARKER_DISABLED) == 0) {
		float pos[2];
		float p[2];

		add_v2_v2v2(pos, marker->pos, track->offset);

		ED_clip_point_undistorted_pos(sc, pos, pos);

		sub_v2_v2v2(p, pos, marker_pos);

		if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
		                        marker->pattern_corners[2], marker->pattern_corners[3]))
		{
			if (tiny) glPointSize(3.0f);
			else glPointSize(4.0f);
			glBegin(GL_POINTS);
			glVertex2f(pos[0], pos[1]);
			glEnd();
			glPointSize(1.0f);
		}
		else {
			if (!tiny) glLineWidth(3.0f);
			glBegin(GL_LINES);
			glVertex2f(pos[0] + px[0] * 2, pos[1]);
			glVertex2f(pos[0] + px[0] * 8, pos[1]);

			glVertex2f(pos[0] - px[0] * 2, pos[1]);
			glVertex2f(pos[0] - px[0] * 8, pos[1]);

			glVertex2f(pos[0], pos[1] - px[1] * 2);
			glVertex2f(pos[0], pos[1] - px[1] * 8);

			glVertex2f(pos[0], pos[1] + px[1] * 2);
			glVertex2f(pos[0], pos[1] + px[1] * 8);
			glEnd();
			if (!tiny) glLineWidth(1.0f);
		}
	}

	/* pattern and search outline */
	glPushMatrix();
	glTranslatef(marker_pos[0], marker_pos[1], 0);

	if (!tiny)
		glLineWidth(3.0f);

	if (sc->flag & SC_SHOW_MARKER_PATTERN) {
		glBegin(GL_LINE_LOOP);
		glVertex2fv(marker->pattern_corners[0]);
		glVertex2fv(marker->pattern_corners[1]);
		glVertex2fv(marker->pattern_corners[2]);
		glVertex2fv(marker->pattern_corners[3]);
		glEnd();
	}

	show_search = TRACK_VIEW_SELECTED(sc, track) &&
	              ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0);
	if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) {
		glBegin(GL_LINE_LOOP);
		glVertex2f(marker->search_min[0], marker->search_min[1]);
		glVertex2f(marker->search_max[0], marker->search_min[1]);
		glVertex2f(marker->search_max[0], marker->search_max[1]);
		glVertex2f(marker->search_min[0], marker->search_max[1]);
		glEnd();
	}
	glPopMatrix();

	if (!tiny)
		glLineWidth(1.0f);
}

static void track_colors(MovieTrackingTrack *track, int act, float col[3], float scol[3])
{
	if (track->flag & TRACK_CUSTOMCOLOR) {
		if (act)
			UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
		else
			copy_v3_v3(scol, track->color);

		mul_v3_v3fl(col, track->color, 0.5f);
	}
	else {
		UI_GetThemeColor3fv(TH_MARKER, col);

		if (act)
			UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
		else
			UI_GetThemeColor3fv(TH_SEL_MARKER, scol);
	}
}

static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
                              float marker_pos[2], int width, int height, int act, int sel)
{
	int tiny = sc->flag & SC_SHOW_TINY_MARKER;
	int show_search = 0;
	float col[3], scol[3], px[2];

	track_colors(track, act, col, scol);

	px[0] = 1.0f / width / sc->zoom;
	px[1] = 1.0f / height / sc->zoom;

	/* marker position and offset position */
	if ((track->flag & SELECT) == sel && (marker->flag & MARKER_DISABLED) == 0) {
		float pos[2], p[2];

		if (track->flag & TRACK_LOCKED) {
			if (act)
				UI_ThemeColor(TH_ACT_MARKER);
			else if (track->flag & SELECT)
				UI_ThemeColorShade(TH_LOCK_MARKER, 64);
			else
				UI_ThemeColor(TH_LOCK_MARKER);
		}
		else {
			if (track->flag & SELECT)
				glColor3fv(scol);
			else
				glColor3fv(col);
		}

		add_v2_v2v2(pos, marker->pos, track->offset);
		ED_clip_point_undistorted_pos(sc, pos, pos);

		sub_v2_v2v2(p, pos, marker_pos);

		if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
		                        marker->pattern_corners[2], marker->pattern_corners[3]))
		{
			if (!tiny)
				glPointSize(2.0f);

			glBegin(GL_POINTS);
			glVertex2f(pos[0], pos[1]);
			glEnd();

			if (!tiny)
				glPointSize(1.0f);
		}
		else {
			glBegin(GL_LINES);
			glVertex2f(pos[0] + px[0] * 3, pos[1]);
			glVertex2f(pos[0] + px[0] * 7, pos[1]);

			glVertex2f(pos[0] - px[0] * 3, pos[1]);
			glVertex2f(pos[0] - px[0] * 7, pos[1]);

			glVertex2f(pos[0], pos[1] - px[1] * 3);
			glVertex2f(pos[0], pos[1] - px[1] * 7);

			glVertex2f(pos[0], pos[1] + px[1] * 3);
			glVertex2f(pos[0], pos[1] + px[1] * 7);
			glEnd();

			glColor3f(0.0f, 0.0f, 0.0f);
			glLineStipple(3, 0xaaaa);
			glEnable(GL_LINE_STIPPLE);
			glEnable(GL_COLOR_LOGIC_OP);
			glLogicOp(GL_NOR);

			glBegin(GL_LINES);
			glVertex2fv(pos);
			glVertex2fv(marker_pos);
			glEnd();

			glDisable(GL_COLOR_LOGIC_OP);
			glDisable(GL_LINE_STIPPLE);
		}
	}

	/* pattern */
	glPushMatrix();
	glTranslatef(marker_pos[0], marker_pos[1], 0);

	if (tiny) {
		glLineStipple(3, 0xaaaa);
		glEnable(GL_LINE_STIPPLE);
	}

	if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
		if (track->flag & TRACK_LOCKED) {
			if (act)
				UI_ThemeColor(TH_ACT_MARKER);
			else if (track->pat_flag & SELECT)
				UI_ThemeColorShade(TH_LOCK_MARKER, 64);
			else UI_ThemeColor(TH_LOCK_MARKER);
		}
		else if (marker->flag & MARKER_DISABLED) {
			if (act)
				UI_ThemeColor(TH_ACT_MARKER);
			else if (track->pat_flag & SELECT)
				UI_ThemeColorShade(TH_DIS_MARKER, 128);
			else UI_ThemeColor(TH_DIS_MARKER);
		}
		else {
			if (track->pat_flag & SELECT)
				glColor3fv(scol);
			else glColor3fv(col);
		}

		glBegin(GL_LINE_LOOP);
		glVertex2fv(marker->pattern_corners[0]);
		glVertex2fv(marker->pattern_corners[1]);
		glVertex2fv(marker->pattern_corners[2]);
		glVertex2fv(marker->pattern_corners[3]);
		glEnd();
	}

	/* search */
	show_search = TRACK_VIEW_SELECTED(sc, track) &&
	              ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0);
	if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
		if (track->flag & TRACK_LOCKED) {
			if (act)
				UI_ThemeColor(TH_ACT_MARKER);
			else if (track->search_flag & SELECT)
				UI_ThemeColorShade(TH_LOCK_MARKER, 64);
			else UI_ThemeColor(TH_LOCK_MARKER);
		}
		else if (marker->flag & MARKER_DISABLED) {
			if (act)
				UI_ThemeColor(TH_ACT_MARKER);
			else if (track->search_flag & SELECT)
				UI_ThemeColorShade(TH_DIS_MARKER, 128);
			else UI_ThemeColor(TH_DIS_MARKER);
		}
		else {
			if (track->search_flag & SELECT)
				glColor3fv(scol);
			else
				glColor3fv(col);
		}

		glBegin(GL_LINE_LOOP);
		glVertex2f(marker->search_min[0], marker->search_min[1]);
		glVertex2f(marker->search_max[0], marker->search_min[1]);
		glVertex2f(marker->search_max[0], marker->search_max[1]);
		glVertex2f(marker->search_min[0], marker->search_max[1]);
		glEnd();
	}

	if (tiny)
		glDisable(GL_LINE_STIPPLE);

	glPopMatrix();
}

static float get_shortest_pattern_side(MovieTrackingMarker *marker)
{
	int i, next;
	float len = FLT_MAX;

	for (i = 0; i < 4; i++) {
		float cur_len;

		next = (i + 1) % 4;

		cur_len = len_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]);

		len = min_ff(cur_len, len);
	}

	return len;
}

static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2])
{
	float tdx, tdy;

	tdx = dx;
	tdy = dy;

	if (outline) {
		tdx += px[0];
		tdy += px[1];
	}

	glBegin(GL_QUADS);
	glVertex3f(x - tdx, y + tdy, 0.0f);
	glVertex3f(x + tdx, y + tdy, 0.0f);
	glVertex3f(x + tdx, y - tdy, 0.0f);
	glVertex3f(x - tdx, y - tdy, 0.0f);
	glEnd();
}

static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2])
{
	float tdx, tdy;

	tdx = dx * 2.0f;
	tdy = dy * 2.0f;

	if (outline) {
		tdx += px[0];
		tdy += px[1];
	}

	glBegin(GL_TRIANGLES);
	glVertex3f(x,       y,       0.0f);
	glVertex3f(x - tdx, y,       0.0f);
	glVertex3f(x,       y + tdy, 0.0f);
	glEnd();
}

static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
                                    float marker_pos[2], int outline, int sel, int act, int width, int height)
{
	float dx, dy, patdx, patdy, searchdx, searchdy;
	int tiny = sc->flag & SC_SHOW_TINY_MARKER;
	float col[3], scol[3], px[2], side;

	if ((tiny && outline) || (marker->flag & MARKER_DISABLED))
		return;

	if (!TRACK_VIEW_SELECTED(sc, track) || track->flag & TRACK_LOCKED)
		return;

	track_colors(track, act, col, scol);

	if (outline) {
		glLineWidth(3.0f);
		UI_ThemeColor(TH_MARKER_OUTLINE);
	}

	glPushMatrix();
	glTranslatef(marker_pos[0], marker_pos[1], 0);

	dx = 6.0f / width / sc->zoom;
	dy = 6.0f / height / sc->zoom;

	side = get_shortest_pattern_side(marker);
	patdx = min_ff(dx * 2.0f / 3.0f, side / 6.0f) * UI_DPI_FAC;
	patdy = min_ff(dy * 2.0f / 3.0f, side * width / height / 6.0f) * UI_DPI_FAC;

	searchdx = min_ff(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f) * UI_DPI_FAC;
	searchdy = min_ff(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f) * UI_DPI_FAC;

	px[0] = 1.0f / sc->zoom / width / sc->scale;
	px[1] = 1.0f / sc->zoom / height / sc->scale;

	if ((sc->flag & SC_SHOW_MARKER_SEARCH) && ((track->search_flag & SELECT) == sel || outline)) {
		if (!outline) {
			if (track->search_flag & SELECT)
				glColor3fv(scol);
			else
				glColor3fv(col);
		}

		/* search offset square */
		draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px);

		/* search re-sizing triangle */
		draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px);
	}

	if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) {
		int i;
		float pat_min[2], pat_max[2];
/*		float dx = 12.0f / width, dy = 12.0f / height;*/ /* XXX UNUSED */
		float tilt_ctrl[2];

		if (!outline) {
			if (track->pat_flag & SELECT)
				glColor3fv(scol);
			else
				glColor3fv(col);
		}

		/* pattern's corners sliding squares */
		for (i = 0; i < 4; i++) {
			draw_marker_slide_square(marker->pattern_corners[i][0], marker->pattern_corners[i][1],
			                         patdx / 1.5f, patdy / 1.5f, outline, px);
		}

		/* ** sliders to control overall pattern  ** */
		add_v2_v2v2(tilt_ctrl, marker->pattern_corners[1], marker->pattern_corners[2]);

		BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);

		glEnable(GL_LINE_STIPPLE);
		glLineStipple(3, 0xaaaa);

#if 0
		/* TODO: disable for now, needs better approach visualizing this */

		glBegin(GL_LINE_LOOP);
		glVertex2f(pat_min[0] - dx, pat_min[1] - dy);
		glVertex2f(pat_max[0] + dx, pat_min[1] - dy);
		glVertex2f(pat_max[0] + dx, pat_max[1] + dy);
		glVertex2f(pat_min[0] - dx, pat_max[1] + dy);
		glEnd();

		/* marker's offset slider */
		draw_marker_slide_square(pat_min[0] - dx, pat_max[1] + dy, patdx, patdy, outline, px);

		/* pattern re-sizing triangle */
		draw_marker_slide_triangle(pat_max[0] + dx, pat_min[1] - dy, patdx, patdy, outline, px);
#endif

		glBegin(GL_LINES);
		glVertex2f(0.0f, 0.0f);
		glVertex2fv(tilt_ctrl);
		glEnd();

		glDisable(GL_LINE_STIPPLE);


		/* slider to control pattern tilt */
		draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px);
	}

	glPopMatrix();

	if (outline)
		glLineWidth(1.0f);
}

static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
                              float marker_pos[2], int act, int width, int height, float zoomx, float zoomy)
{
	char str[128] = {0}, state[64] = {0};
	float dx = 0.0f, dy = 0.0f, fontsize, pos[3];
	uiStyle *style = U.uistyles.first;
	int fontid = style->widget.uifont_id;

	if (!TRACK_VIEW_SELECTED(sc, track))
		return;

	BLF_size(fontid, 11.0f, U.dpi);
	fontsize = BLF_height_max(fontid);

	if (marker->flag & MARKER_DISABLED) {
		if (act)
			UI_ThemeColor(TH_ACT_MARKER);
		else
			UI_ThemeColorShade(TH_DIS_MARKER, 128);
	}
	else {
		if (act)
			UI_ThemeColor(TH_ACT_MARKER);
		else
			UI_ThemeColor(TH_SEL_MARKER);
	}

	if ((sc->flag & SC_SHOW_MARKER_SEARCH) &&
	    ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0))
	{
		dx = marker->search_min[0];
		dy = marker->search_min[1];
	}
	else if (sc->flag & SC_SHOW_MARKER_PATTERN) {
		float pat_min[2], pat_max[2];

		BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
		dx = pat_min[0];
		dy = pat_min[1];
	}

	pos[0] = (marker_pos[0] + dx) * width;
	pos[1] = (marker_pos[1] + dy) * height;
	pos[2] = 0.0f;

	mul_m4_v3(sc->stabmat, pos);

	pos[0] = pos[0] * zoomx;
	pos[1] = pos[1] * zoomy - fontsize;

	if (marker->flag & MARKER_DISABLED)
		strcpy(state, "disabled");
	else if (marker->framenr != ED_space_clip_get_clip_frame_number(sc))
		strcpy(state, "estimated");
	else if (marker->flag & MARKER_TRACKED)
		strcpy(state, "tracked");
	else
		strcpy(state, "keyframed");

	if (state[0])
		BLI_snprintf(str, sizeof(str), "%s: %s", track->name, state);
	else
		BLI_snprintf(str, sizeof(str), "%s", track->name);

	BLF_position(fontid, pos[0], pos[1], 0.0f);
	BLF_draw(fontid, str, sizeof(str));
	pos[1] -= fontsize;

	if (track->flag & TRACK_HAS_BUNDLE) {
		BLI_snprintf(str, sizeof(str), "Average error: %.3f", track->error);
		BLF_position(fontid, pos[0], pos[1], 0.0f);
		BLF_draw(fontid, str, sizeof(str));
		pos[1] -= fontsize;
	}

	if (track->flag & TRACK_LOCKED) {
		BLF_position(fontid, pos[0], pos[1], 0.0f);
		BLF_draw(fontid, "locked", 6);
	}
}

static void view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony)
{
	/* express given coordinates as proportional values */
	x = -v2d->cur.xmin / BLI_rctf_size_x(&v2d->cur);
	y = -v2d->cur.ymin / BLI_rctf_size_y(&v2d->cur);

	/* convert proportional distances to screen coordinates */
	*regionx = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask);
	*regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask);
}

static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
                                 int width, int height, float zoomx, float zoomy)
{
	float x, y;
	MovieTracking *tracking = &clip->tracking;
	ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
	MovieTrackingTrack *track, *act_track;
	MovieTrackingMarker *marker;
	int framenr = ED_space_clip_get_clip_frame_number(sc);
	int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
	float *marker_pos = NULL, *fp, *active_pos = NULL, cur_pos[2];

	/* ** find window pixel coordinates of origin ** */

	/* UI_view2d_to_region_no_clip return integer values, this could
	 * lead to 1px flickering when view is locked to selection during playbeck.
	 * to avoid this flickering, calculate base point in the same way as it happens
	 * in UI_view2d_to_region_no_clip, but do it in floats here */

	view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);

	glPushMatrix();
	glTranslatef(x, y, 0);

	glPushMatrix();
	glScalef(zoomx, zoomy, 0);
	glMultMatrixf(sc->stabmat);
	glScalef(width, height, 0);

	act_track = BKE_tracking_track_get_active(tracking);

	if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
		int count = 0;

		/* count */
		track = tracksbase->first;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0) {
				marker = BKE_tracking_marker_get(track, framenr);

				if (MARKER_VISIBLE(sc, track, marker))
					count++;
			}

			track = track->next;
		}

		/* undistort */
		if (count) {
			marker_pos = MEM_callocN(2 * sizeof(float) * count, "draw_tracking_tracks marker_pos");

			track = tracksbase->first;
			fp = marker_pos;
			while (track) {
				if ((track->flag & TRACK_HIDDEN) == 0) {
					marker = BKE_tracking_marker_get(track, framenr);

					if (MARKER_VISIBLE(sc, track, marker)) {
						ED_clip_point_undistorted_pos(sc, marker->pos, fp);

						if (track == act_track)
							active_pos = fp;

						fp += 2;
					}
				}

				track = track->next;
			}
		}
	}

	if (sc->flag & SC_SHOW_TRACK_PATH) {
		track = tracksbase->first;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0)
				draw_track_path(sc, clip, track);

			track = track->next;
		}
	}

	/* markers outline and non-selected areas */
	track = tracksbase->first;
	fp = marker_pos;
	while (track) {
		if ((track->flag & TRACK_HIDDEN) == 0) {
			marker = BKE_tracking_marker_get(track, framenr);

			if (MARKER_VISIBLE(sc, track, marker)) {
				copy_v2_v2(cur_pos, fp ? fp : marker->pos);

				draw_marker_outline(sc, track, marker, cur_pos, width, height);
				draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0);
				draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height);
				draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height);

				if (fp)
					fp += 2;
			}
		}

		track = track->next;
	}

	/* selected areas only, so selection wouldn't be overlapped by
	 * non-selected areas */
	track = tracksbase->first;
	fp = marker_pos;
	while (track) {
		if ((track->flag & TRACK_HIDDEN) == 0) {
			int act = track == act_track;
			marker = BKE_tracking_marker_get(track, framenr);

			if (MARKER_VISIBLE(sc, track, marker)) {
				if (!act) {
					copy_v2_v2(cur_pos, fp ? fp : marker->pos);

					draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1);
					draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height);
				}

				if (fp)
					fp += 2;
			}
		}

		track = track->next;
	}

	/* active marker would be displayed on top of everything else */
	if (act_track) {
		if ((act_track->flag & TRACK_HIDDEN) == 0) {
			marker = BKE_tracking_marker_get(act_track, framenr);

			if (MARKER_VISIBLE(sc, act_track, marker)) {
				copy_v2_v2(cur_pos, active_pos ? active_pos : marker->pos);

				draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1);
				draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height);
			}
		}
	}

	if (sc->flag & SC_SHOW_BUNDLES) {
		MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
		float pos[4], vec[4], mat[4][4], aspy;

		glEnable(GL_POINT_SMOOTH);
		glPointSize(3.0f);

		aspy = 1.0f / clip->tracking.camera.pixel_aspect;
		BKE_tracking_get_projection_matrix(tracking, object, framenr, width, height, mat);

		track = tracksbase->first;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0 && track->flag & TRACK_HAS_BUNDLE) {
				marker = BKE_tracking_marker_get(track, framenr);

				if (MARKER_VISIBLE(sc, track, marker)) {
					float npos[2];
					copy_v3_v3(vec, track->bundle_pos);
					vec[3] = 1;

					mul_v4_m4v4(pos, mat, vec);

					pos[0] = (pos[0] / (pos[3] * 2.0f) + 0.5f) * width;
					pos[1] = (pos[1] / (pos[3] * 2.0f) + 0.5f) * height * aspy;

					BKE_tracking_distort_v2(tracking, pos, npos);

					if (npos[0] >= 0.0f && npos[1] >= 0.0f && npos[0] <= width && npos[1] <= height * aspy) {
						vec[0] = (marker->pos[0] + track->offset[0]) * width;
						vec[1] = (marker->pos[1] + track->offset[1]) * height * aspy;

						sub_v2_v2(vec, npos);

						if (len_v2(vec) < 3.0f)
							glColor3f(0.0f, 1.0f, 0.0f);
						else
							glColor3f(1.0f, 0.0f, 0.0f);

						glBegin(GL_POINTS);
						if (undistort)
							glVertex3f(pos[0] / width, pos[1] / (height * aspy), 0);
						else
							glVertex3f(npos[0] / width, npos[1] / (height * aspy), 0);
						glEnd();
					}
				}
			}

			track = track->next;
		}

		glPointSize(1.0f);
		glDisable(GL_POINT_SMOOTH);
	}

	glPopMatrix();

	if (sc->flag & SC_SHOW_NAMES) {
		/* scaling should be cleared before drawing texts, otherwise font would also be scaled */
		track = tracksbase->first;
		fp = marker_pos;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0) {
				marker = BKE_tracking_marker_get(track, framenr);

				if (MARKER_VISIBLE(sc, track, marker)) {
					int act = track == act_track;

					copy_v2_v2(cur_pos, fp ? fp : marker->pos);

					draw_marker_texts(sc, track, marker, cur_pos, act, width, height, zoomx, zoomy);

					if (fp)
						fp += 2;
				}
			}

			track = track->next;
		}
	}

	glPopMatrix();

	if (marker_pos)
		MEM_freeN(marker_pos);
}

static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
                            int width, int height, float zoomx, float zoomy)
{
	float x, y;
	const int n = 10;
	int i, j, a;
	float pos[2], tpos[2], grid[11][11][2];
	MovieTracking *tracking = &clip->tracking;
	bGPdata *gpd = NULL;
	float aspy = 1.0f / tracking->camera.pixel_aspect;
	float dx = (float)width / n, dy = (float)height / n * aspy;
	float offsx = 0.0f, offsy = 0.0f;

	if (sc->mode != SC_MODE_DISTORTION)
		return;

	if (!tracking->camera.focal)
		return;

	if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0)
		return;

	view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);

	glPushMatrix();
	glTranslatef(x, y, 0);
	glScalef(zoomx, zoomy, 0);
	glMultMatrixf(sc->stabmat);
	glScalef(width, height, 0);

	/* grid */
	if (sc->flag & SC_SHOW_GRID) {
		float val[4][2], idx[4][2];
		float min[2], max[2];

		for (a = 0; a < 4; a++) {
			if (a < 2)
				val[a][a % 2] = FLT_MAX;
			else
				val[a][a % 2] = -FLT_MAX;
		}

		zero_v2(pos);
		for (i = 0; i <= n; i++) {
			for (j = 0; j <= n; j++) {
				if (i == 0 || j == 0 || i == n || j == n) {
					BKE_tracking_distort_v2(tracking, pos, tpos);

					for (a = 0; a < 4; a++) {
						int ok;

						if (a < 2)
							ok = tpos[a % 2] < val[a][a % 2];
						else
							ok = tpos[a % 2] > val[a][a % 2];

						if (ok) {
							copy_v2_v2(val[a], tpos);
							idx[a][0] = j;
							idx[a][1] = i;
						}
					}
				}

				pos[0] += dx;
			}

			pos[0] = 0.0f;
			pos[1] += dy;
		}

		INIT_MINMAX2(min, max);

		for (a = 0; a < 4; a++) {
			pos[0] = idx[a][0] * dx;
			pos[1] = idx[a][1] * dy;

			BKE_tracking_undistort_v2(tracking, pos, tpos);

			minmax_v2v2_v2(min, max, tpos);
		}

		copy_v2_v2(pos, min);
		dx = (max[0] - min[0]) / n;
		dy = (max[1] - min[1]) / n;

		for (i = 0; i <= n; i++) {
			for (j = 0; j <= n; j++) {
				BKE_tracking_distort_v2(tracking, pos, grid[i][j]);

				grid[i][j][0] /= width;
				grid[i][j][1] /= height * aspy;

				pos[0] += dx;
			}

			pos[0] = min[0];
			pos[1] += dy;
		}

		glColor3f(1.0f, 0.0f, 0.0f);

		for (i = 0; i <= n; i++) {
			glBegin(GL_LINE_STRIP);
			for (j = 0; j <= n; j++) {
				glVertex2fv(grid[i][j]);
			}
			glEnd();
		}

		for (j = 0; j <= n; j++) {
			glBegin(GL_LINE_STRIP);
			for (i = 0; i <= n; i++) {
				glVertex2fv(grid[i][j]);
			}
			glEnd();
		}
	}

	if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
		MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);

		if (track) {
			int framenr = ED_space_clip_get_clip_frame_number(sc);
			MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);

			offsx = marker->pos[0];
			offsy = marker->pos[1];

			gpd = track->gpd;
		}

	}
	else {
		gpd = clip->gpd;
	}

	if (sc->flag & SC_MANUAL_CALIBRATION && gpd) {
		bGPDlayer *layer = gpd->layers.first;

		while (layer) {
			bGPDframe *frame = layer->frames.first;

			if (layer->flag & GP_LAYER_HIDE) {
				layer = layer->next;
				continue;
			}

			glColor4fv(layer->color);
			glLineWidth(layer->thickness);
			glPointSize((float)(layer->thickness + 2));

			while (frame) {
				bGPDstroke *stroke = frame->strokes.first;

				while (stroke) {
					if (stroke->flag & GP_STROKE_2DSPACE) {
						if (stroke->totpoints > 1) {
							glBegin(GL_LINE_STRIP);
							for (i = 0; i < stroke->totpoints - 1; i++) {
								float npos[2], dpos[2], len;
								int steps;

								pos[0] = (stroke->points[i].x + offsx) * width;
								pos[1] = (stroke->points[i].y + offsy) * height * aspy;

								npos[0] = (stroke->points[i + 1].x + offsx) * width;
								npos[1] = (stroke->points[i + 1].y + offsy) * height * aspy;

								len = len_v2v2(pos, npos);
								steps = ceil(len / 5.0f);

								/* we want to distort only long straight lines */
								if (stroke->totpoints == 2) {
									BKE_tracking_undistort_v2(tracking, pos, pos);
									BKE_tracking_undistort_v2(tracking, npos, npos);
								}

								sub_v2_v2v2(dpos, npos, pos);
								mul_v2_fl(dpos, 1.0f / steps);

								for (j = 0; j <= steps; j++) {
									BKE_tracking_distort_v2(tracking, pos, tpos);
									glVertex2f(tpos[0] / width, tpos[1] / (height * aspy));

									add_v2_v2(pos, dpos);
								}
							}
							glEnd();
						}
						else if (stroke->totpoints == 1) {
							glBegin(GL_POINTS);
							glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy);
							glEnd();
						}
					}

					stroke = stroke->next;
				}

				frame = frame->next;
			}

			layer = layer->next;
		}

		glLineWidth(1.0f);
		glPointSize(1.0f);
	}

	glPopMatrix();
}

void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
{
	MovieClip *clip = ED_space_clip_get_clip(sc);
	Scene *scene = CTX_data_scene(C);
	ImBuf *ibuf;
	int width, height;
	float zoomx, zoomy;

	ED_space_clip_get_size(sc, &width, &height);
	ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);

	/* if no clip, nothing to do */
	if (!clip) {
		ED_region_grid_draw(ar, zoomx, zoomy);
		return;
	}

	if (sc->flag & SC_SHOW_STABLE) {
		float smat[4][4], ismat[4][4];

		ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc, &sc->scale, &sc->angle);

		if (ibuf) {
			float loc[2];
			float aspect = clip->tracking.camera.pixel_aspect;

			if (width != ibuf->x)
				mul_v2_v2fl(loc, sc->loc, (float)width / ibuf->x);
			else
				copy_v2_v2(loc, sc->loc);

			BKE_tracking_stabilization_data_to_mat4(width, height, aspect, loc, sc->scale, sc->angle, sc->stabmat);

			unit_m4(smat);
			smat[0][0] = 1.0f / width;
			smat[1][1] = 1.0f / height;
			invert_m4_m4(ismat, smat);

			mul_serie_m4(sc->unistabmat, smat, sc->stabmat, ismat, NULL, NULL, NULL, NULL, NULL);
		}
	}
	else {
		ibuf = ED_space_clip_get_buffer(sc);

		zero_v2(sc->loc);
		sc->scale = 1.0f;
		unit_m4(sc->stabmat);
		unit_m4(sc->unistabmat);
	}

	if (ibuf) {
		draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy);
		IMB_freeImBuf(ibuf);
	}
	else {
		ED_region_grid_draw(ar, zoomx, zoomy);
	}

	if (width && height) {
		draw_stabilization_border(sc, ar, width, height, zoomx, zoomy);
		draw_tracking_tracks(sc, ar, clip, width, height, zoomx, zoomy);
		draw_distortion(sc, ar, clip, width, height, zoomx, zoomy);
	}

	draw_movieclip_cache(sc, ar, clip, scene);
	draw_movieclip_notes(sc, ar);
}

/* draw grease pencil */
void clip_draw_grease_pencil(bContext *C, int onlyv2d)
{
	SpaceClip *sc = CTX_wm_space_clip(C);
	MovieClip *clip = ED_space_clip_get_clip(sc);

	if (!clip)
		return;

	if (onlyv2d) {
		/* if manual calibration is used then grease pencil data is already
		 * drawn in draw_distortion */
		if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || sc->mode != SC_MODE_DISTORTION) {
			glPushMatrix();
			glMultMatrixf(sc->unistabmat);

			if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
				MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);

				if (track) {
					int framenr = ED_space_clip_get_clip_frame_number(sc);
					MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);

					glTranslatef(marker->pos[0], marker->pos[1], 0.0f);
				}
			}

			draw_gpencil_2dimage(C);

			glPopMatrix();
		}
	}
	else {
		draw_gpencil_view2d(C, 0);
	}
}
