void ExecutionGroup::setRenderBorder(float xmin, float xmax, float ymin, float ymax)
{
	NodeOperation *operation = this->getOutputOperation();

	if (operation->isOutputOperation(true)) {
		/* Basically, setting border need to happen for only operations
		 * which operates in render resolution buffers (like compositor
		 * output nodes).
		 *
		 * In this cases adding border will lead to mapping coordinates
		 * from output buffer space to input buffer spaces when executing
		 * operation.
		 *
		 * But nodes like viewer and file output just shall display or
		 * safe the same exact buffer which goes to their input, no need
		 * in any kind of coordinates mapping.
		 */

		bool operationNeedsBorder = !(operation->isViewerOperation() ||
		                              operation->isPreviewOperation() ||
		                              operation->isFileOutputOperation());

		if (operationNeedsBorder) {
			BLI_rcti_init(&this->m_viewerBorder, xmin * this->m_width, xmax * this->m_width,
			              ymin * this->m_height, ymax * this->m_height);
		}
	}
}
static int render_view3d_disprect(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, rcti *disprect)
{
	/* copied code from view3d_draw.c */
	rctf viewborder;
	int draw_border;
	
	if (rv3d->persp == RV3D_CAMOB)
		draw_border = (scene->r.mode & R_BORDER) != 0;
	else
		draw_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;

	if (draw_border) {
		if (rv3d->persp == RV3D_CAMOB) {
			ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
			
			disprect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
			disprect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
			disprect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
			disprect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
		}
		else {
			disprect->xmin = v3d->render_border.xmin * ar->winx;
			disprect->xmax = v3d->render_border.xmax * ar->winx;
			disprect->ymin = v3d->render_border.ymin * ar->winy;
			disprect->ymax = v3d->render_border.ymax * ar->winy;
		}
		
		return 1;
	}
	
	BLI_rcti_init(disprect, 0, 0, 0, 0);
	return 0;
}
inline void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int xChunk, const unsigned int yChunk) const
{
	const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
	const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);

	if (this->m_singleThreaded) {
		BLI_rcti_init(rect, this->m_viewerBorder.xmin, border_width, this->m_viewerBorder.ymin, border_height);
	}
	else {
		const unsigned int minx = xChunk * this->m_chunkSize + this->m_viewerBorder.xmin;
		const unsigned int miny = yChunk * this->m_chunkSize + this->m_viewerBorder.ymin;
		const unsigned int width = min((unsigned int) this->m_viewerBorder.xmax, this->m_width);
		const unsigned int height = min((unsigned int) this->m_viewerBorder.ymax, this->m_height);
		BLI_rcti_init(rect, min(minx, this->m_width), min(minx + this->m_chunkSize, width), min(miny, this->m_height), min(miny + this->m_chunkSize, height));
	}
}
bool NodeOperation::determineDependingAreaOfInterest(rcti *input,
                                                     ReadBufferOperation *readOperation,
                                                     rcti *output)
{
  if (isInputOperation()) {
    BLI_rcti_init(output, input->xmin, input->xmax, input->ymin, input->ymax);
    return false;
  }
  else {
    rcti tempOutput;
    bool first = true;
    for (int i = 0; i < getNumberOfInputSockets(); i++) {
      NodeOperation *inputOperation = this->getInputOperation(i);
      if (inputOperation &&
          inputOperation->determineDependingAreaOfInterest(input, readOperation, &tempOutput)) {
        if (first) {
          output->xmin = tempOutput.xmin;
          output->ymin = tempOutput.ymin;
          output->xmax = tempOutput.xmax;
          output->ymax = tempOutput.ymax;
          first = false;
        }
        else {
          output->xmin = min(output->xmin, tempOutput.xmin);
          output->ymin = min(output->ymin, tempOutput.ymin);
          output->xmax = max(output->xmax, tempOutput.xmax);
          output->ymax = max(output->ymax, tempOutput.ymax);
        }
      }
    }
    return !first;
  }
}
bool ProjectorLensDistortionOperation::determineDependingAreaOfInterest(
    rcti *input, ReadBufferOperation *readOperation, rcti *output)
{
  rcti newInput;
  if (this->m_dispersionAvailable) {
    newInput.ymax = input->ymax;
    newInput.ymin = input->ymin;
    newInput.xmin = input->xmin - this->m_kr2 - 2;
    newInput.xmax = input->xmax + this->m_kr2 + 2;
  }
  else {
    rcti dispInput;
    BLI_rcti_init(&dispInput, 0, 5, 0, 5);
    if (this->getInputOperation(1)->determineDependingAreaOfInterest(
            &dispInput, readOperation, output)) {
      return true;
    }
    newInput.xmin = input->xmin - 7; /* (0.25f * 20 * 1) + 2 == worse case dispersion */
    newInput.ymin = input->ymin;
    newInput.ymax = input->ymax;
    newInput.xmax = input->xmax + 7; /* (0.25f * 20 * 1) + 2 == worse case dispersion */
  }
  if (this->getInputOperation(0)->determineDependingAreaOfInterest(
          &newInput, readOperation, output)) {
    return true;
  }
  return false;
}
void ExecutionGroup::determineResolution(unsigned int resolution[2])
{
	NodeOperation *operation = this->getOutputOperation();
	resolution[0] = operation->getWidth();
	resolution[1] = operation->getHeight();
	this->setResolution(resolution);
	BLI_rcti_init(&this->m_viewerBorder, 0, this->m_width, 0, this->m_height);
}
bool ReadBufferOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
{
	if (this == readOperation) {
		BLI_rcti_init(output, input->xmin, input->xmax, input->ymin, input->ymax);
		return true;
	}
	return false;
}
void ExecutionGroup::setViewerBorder(float xmin, float xmax, float ymin, float ymax)
{
	NodeOperation *operation = this->getOutputOperation();

	if (operation->isViewerOperation() || operation->isPreviewOperation()) {
		BLI_rcti_init(&this->m_viewerBorder, xmin * this->m_width, xmax * this->m_width,
		              ymin * this->m_height, ymax * this->m_height);
	}
}
MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect)
{
	BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
	this->m_memoryProxy = memoryProxy;
	this->m_chunkNumber = -1;
	this->m_buffer = (float *)MEM_mallocN(sizeof(float) * determineBufferSize() * COM_NUMBER_OF_CHANNELS, "COM_MemoryBuffer");
	this->m_state = COM_MB_TEMPORARILY;
	this->m_datatype = COM_DT_COLOR;
	this->m_chunkWidth = this->m_rect.xmax - this->m_rect.xmin;
}
bool ExecutionGroup::scheduleChunkWhenPossible(ExecutionSystem *graph, int xChunk, int yChunk)
{
	if (xChunk < 0 || xChunk >= (int)this->m_numberOfXChunks) {
		return true;
	}
	if (yChunk < 0 || yChunk >= (int)this->m_numberOfYChunks) {
		return true;
	}
	int chunkNumber = yChunk * this->m_numberOfXChunks + xChunk;
	// chunk is already executed
	if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_EXECUTED) {
		return true;
	}

	// chunk is scheduled, but not executed
	if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED) {
		return false;
	}

	// chunk is nor executed nor scheduled.
	vector<MemoryProxy *> memoryProxies;
	this->determineDependingMemoryProxies(&memoryProxies);

	rcti rect;
	determineChunkRect(&rect, xChunk, yChunk);
	unsigned int index;
	bool canBeExecuted = true;
	rcti area;

	for (index = 0; index < this->m_cachedReadOperations.size(); index++) {
		ReadBufferOperation *readOperation = (ReadBufferOperation *)this->m_cachedReadOperations[index];
		BLI_rcti_init(&area, 0, 0, 0, 0);
		MemoryProxy *memoryProxy = memoryProxies[index];
		determineDependingAreaOfInterest(&rect, readOperation, &area);
		ExecutionGroup *group = memoryProxy->getExecutor();

		if (group != NULL) {
			if (!group->scheduleAreaWhenPossible(graph, &area)) {
				canBeExecuted = false;
			}
		}
		else {
			throw "ERROR";
		}
	}

	if (canBeExecuted) {
		scheduleChunk(chunkNumber);
	}

	return false;
}
Exemple #11
0
/* Transform buffer from role to scene linear space using GLSL OCIO conversion
 *
 * See IMB_colormanagement_setup_transform_from_role_glsl description for
 * some more details
 *
 * NOTE: this only works for RGBA buffers!
 */
int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role)
{
	GPUOffScreen *ofs;
	char err_out[256];
	rcti display_rect;

	ofs = GPU_offscreen_create(width, height, err_out);

	if (!ofs)
		return FALSE;

	GPU_offscreen_bind(ofs);

	if (!IMB_colormanagement_setup_transform_from_role_glsl(role, TRUE)) {
		GPU_offscreen_unbind(ofs);
		GPU_offscreen_free(ofs);
		return FALSE;
	}

	BLI_rcti_init(&display_rect, 0, width, 0, height);

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();

	glaDefine2DArea(&display_rect);

	glaDrawPixelsTex(0, 0, width, height, GL_RGBA, GL_FLOAT,
	                 GL_NEAREST, buffer);

	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

	GPU_offscreen_read_pixels(ofs, GL_FLOAT, buffer);

	IMB_colormanagement_finish_glsl_transform();

	/* unbind */
	GPU_offscreen_unbind(ofs);
	GPU_offscreen_free(ofs);

	return TRUE;
}
Exemple #12
0
/* ---------- FILE SELECTION ------------ */
static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const rcti *rect)
{
	FileSelection sel;
	float fxmin, fymin, fxmax, fymax;
	
	View2D *v2d = &ar->v2d;
	rcti rect_view;

	UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin, &fxmin, &fymin);
	UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax, &fxmax, &fymax);

	BLI_rcti_init(&rect_view, (int)(v2d->tot.xmin + fxmin), (int)(v2d->tot.xmin + fxmax), (int)(v2d->tot.ymax - fymin), (int)(v2d->tot.ymax - fymax));

	sel  = ED_fileselect_layout_offset_rect(sfile->layout, &rect_view);
	
	return sel;
}
ExecutionGroup::ExecutionGroup()
{
	this->m_isOutput = false;
	this->m_complex = false;
	this->m_chunkExecutionStates = NULL;
	this->m_bTree = NULL;
	this->m_height = 0;
	this->m_width = 0;
	this->m_cachedMaxReadBufferOffset = 0;
	this->m_numberOfXChunks = 0;
	this->m_numberOfYChunks = 0;
	this->m_numberOfChunks = 0;
	this->m_initialized = false;
	this->m_openCL = false;
	this->m_singleThreaded = false;
	this->m_chunksFinished = 0;
	BLI_rcti_init(&this->m_viewerBorder, 0, 0, 0, 0);
	this->m_executionStartTime = 0;
}
/* ---------- FILE SELECTION ------------ */
static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const rcti *rect_region)
{
	FileSelection sel;
	
	View2D *v2d = &ar->v2d;
	rcti rect_view;
	rctf rect_view_fl;
	rctf rect_region_fl;

	BLI_rctf_rcti_copy(&rect_region_fl, rect_region);

	UI_view2d_region_to_view_rctf(v2d, &rect_region_fl, &rect_view_fl);

	BLI_rcti_init(&rect_view,
	              (int)(v2d->tot.xmin + rect_view_fl.xmin),
	              (int)(v2d->tot.xmin + rect_view_fl.xmax),
	              (int)(v2d->tot.ymax - rect_view_fl.ymin),
	              (int)(v2d->tot.ymax - rect_view_fl.ymax));

	sel  = ED_fileselect_layout_offset_rect(sfile->layout, &rect_view);
	
	return sel;
}
Exemple #15
0
/* used by node view too */
void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_default_view, int channels, int x, int y,
                        const unsigned char cp[4], const float fp[4], const float linearcol[4], int *zp, float *zpf)
{
	rcti color_rect;
	char str[256];
	int dx = 6;
	const int dy = 0.3f * UI_UNIT_Y;
	/* text colors */
	/* XXX colored text not allowed in Blender UI */
#if 0
	unsigned char red[3] = {255, 50, 50};
	unsigned char green[3] = {0, 255, 0};
	unsigned char blue[3] = {100, 100, 255};
#else
	unsigned char red[3] = {255, 255, 255};
	unsigned char green[3] = {255, 255, 255};
	unsigned char blue[3] = {255, 255, 255};
#endif
	float hue = 0, sat = 0, val = 0, lum = 0, u = 0, v = 0;
	float col[4], finalcol[4];

	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);

	/* noisy, high contrast make impossible to read if lower alpha is used. */
	glColor4ub(0, 0, 0, 190);
	glRecti(0.0, 0.0, BLI_rcti_size_x(&ar->winrct) + 1, UI_UNIT_Y);
	glDisable(GL_BLEND);

	BLF_size(blf_mono_font, 11 * U.pixelsize, U.dpi);

	glColor3ub(255, 255, 255);
	BLI_snprintf(str, sizeof(str), "X:%-4d  Y:%-4d |", x, y);
	BLF_position(blf_mono_font, dx, dy, 0);
	BLF_draw_ascii(blf_mono_font, str, sizeof(str));
	dx += BLF_width(blf_mono_font, str, sizeof(str));

	if (zp) {
		glColor3ub(255, 255, 255);
		BLI_snprintf(str, sizeof(str), " Z:%-.4f |", 0.5f + 0.5f * (((float)*zp) / (float)0x7fffffff));
		BLF_position(blf_mono_font, dx, dy, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str, sizeof(str));
	}
	if (zpf) {
		glColor3ub(255, 255, 255);
		BLI_snprintf(str, sizeof(str), " Z:%-.3f |", *zpf);
		BLF_position(blf_mono_font, dx, dy, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str, sizeof(str));
	}

	if (channels >= 3) {
		glColor3ubv(red);
		if (fp)
			BLI_snprintf(str, sizeof(str), "  R:%-.5f", fp[0]);
		else if (cp)
			BLI_snprintf(str, sizeof(str), "  R:%-3d", cp[0]);
		else
			BLI_snprintf(str, sizeof(str), "  R:-");
		BLF_position(blf_mono_font, dx, dy, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str, sizeof(str));
		
		glColor3ubv(green);
		if (fp)
			BLI_snprintf(str, sizeof(str), "  G:%-.5f", fp[1]);
		else if (cp)
			BLI_snprintf(str, sizeof(str), "  G:%-3d", cp[1]);
		else
			BLI_snprintf(str, sizeof(str), "  G:-");
		BLF_position(blf_mono_font, dx, dy, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str, sizeof(str));
		
		glColor3ubv(blue);
		if (fp)
			BLI_snprintf(str, sizeof(str), "  B:%-.5f", fp[2]);
		else if (cp)
			BLI_snprintf(str, sizeof(str), "  B:%-3d", cp[2]);
		else
			BLI_snprintf(str, sizeof(str), "  B:-");
		BLF_position(blf_mono_font, dx, dy, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str, sizeof(str));
		
		if (channels == 4) {
			glColor3ub(255, 255, 255);
			if (fp)
				BLI_snprintf(str, sizeof(str), "  A:%-.4f", fp[3]);
			else if (cp)
				BLI_snprintf(str, sizeof(str), "  A:%-3d", cp[3]);
			else
				BLI_snprintf(str, sizeof(str), "- ");
			BLF_position(blf_mono_font, dx, dy, 0);
			BLF_draw_ascii(blf_mono_font, str, sizeof(str));
			dx += BLF_width(blf_mono_font, str, sizeof(str));
		}

		if (color_manage) {
			float rgba[4];

			copy_v3_v3(rgba, linearcol);
			if (channels == 3)
				rgba[3] = 1.0f;
			else
				rgba[3] = linearcol[3];

			if (use_default_view)
				IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba,  NULL, &scene->display_settings);
			else
				IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba,  &scene->view_settings, &scene->display_settings);

			BLI_snprintf(str, sizeof(str), "  |  CM  R:%-.4f  G:%-.4f  B:%-.4f", rgba[0], rgba[1], rgba[2]);
			BLF_position(blf_mono_font, dx, dy, 0);
			BLF_draw_ascii(blf_mono_font, str, sizeof(str));
			dx += BLF_width(blf_mono_font, str, sizeof(str));
		}
	}
	
	/* color rectangle */
	if (channels == 1) {
		if (fp) {
			col[0] = col[1] = col[2] = fp[0];
		}
		else if (cp) {
			col[0] = col[1] = col[2] = (float)cp[0] / 255.0f;
		}
		else {
			col[0] = col[1] = col[2] = 0.0f;
		}
		col[3] = 1.0f;
	}
	else if (channels == 3) {
		copy_v3_v3(col, linearcol);
		col[3] = 1.0f;
	}
	else if (channels == 4) {
		copy_v4_v4(col, linearcol);
	}
	else {
		BLI_assert(0);
		zero_v4(col);
	}

	if (color_manage) {
		if (use_default_view)
			IMB_colormanagement_pixel_to_display_space_v4(finalcol, col,  NULL, &scene->display_settings);
		else
			IMB_colormanagement_pixel_to_display_space_v4(finalcol, col,  &scene->view_settings, &scene->display_settings);
	}
	else {
		copy_v4_v4(finalcol, col);
	}

	glDisable(GL_BLEND);
	dx += 0.25f * UI_UNIT_X;

	BLI_rcti_init(&color_rect, dx, dx + (1.5f * UI_UNIT_X), 0.15f * UI_UNIT_Y, 0.85f * UI_UNIT_Y);

	if (channels == 4) {
		rcti color_rect_half;
		int color_quater_x, color_quater_y;

		color_rect_half = color_rect;
		color_rect_half.xmax = BLI_rcti_cent_x(&color_rect);
		glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);

		color_rect_half = color_rect;
		color_rect_half.xmin = BLI_rcti_cent_x(&color_rect);

		color_quater_x = BLI_rcti_cent_x(&color_rect_half);
		color_quater_y = BLI_rcti_cent_y(&color_rect_half);

		glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255);
		glRecti(color_rect_half.xmin, color_rect_half.ymin, color_rect_half.xmax, color_rect_half.ymax);

		glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255);
		glRecti(color_quater_x, color_quater_y, color_rect_half.xmax, color_rect_half.ymax);
		glRecti(color_rect_half.xmin, color_rect_half.ymin, color_quater_x, color_quater_y);

		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glColor4f(UNPACK3(finalcol), fp ? fp[3] : (cp[3] / 255.0f));
		glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
		glDisable(GL_BLEND);
	}
	else {
		glColor3fv(finalcol);
		glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
	}

	/* draw outline */
	glColor3ub(128, 128, 128);
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	dx += 1.75f * UI_UNIT_X;

	glColor3ub(255, 255, 255);
	if (channels == 1) {
		if (fp) {
			rgb_to_hsv(fp[0], fp[0], fp[0], &hue, &sat, &val);
			rgb_to_yuv(fp[0], fp[0], fp[0], &lum, &u, &v);
		}
		else if (cp) {
			rgb_to_hsv((float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &hue, &sat, &val);
			rgb_to_yuv((float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &lum, &u, &v);
		}
		
		BLI_snprintf(str, sizeof(str), "V:%-.4f", val);
		BLF_position(blf_mono_font, dx, dy, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str, sizeof(str));

		BLI_snprintf(str, sizeof(str), "   L:%-.4f", lum);
		BLF_position(blf_mono_font, dx, dy, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str, sizeof(str));
	}
	else if (channels >= 3) {
		rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val);
		rgb_to_yuv(finalcol[0], finalcol[1], finalcol[2], &lum, &u, &v);

		BLI_snprintf(str, sizeof(str), "H:%-.4f", hue);
		BLF_position(blf_mono_font, dx, dy, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str, sizeof(str));

		BLI_snprintf(str, sizeof(str), "  S:%-.4f", sat);
		BLF_position(blf_mono_font, dx, dy, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str, sizeof(str));

		BLI_snprintf(str, sizeof(str), "  V:%-.4f", val);
		BLF_position(blf_mono_font, dx, dy, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str, sizeof(str));

		BLI_snprintf(str, sizeof(str), "   L:%-.4f", lum);
		BLF_position(blf_mono_font, dx, dy, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str, sizeof(str));
	}

	(void)dx;
}