int
fz_highlight_selection(fz_context *ctx, fz_text_page *page, fz_bbox rect, fz_bbox *hit_bbox, int hit_max)
{
	fz_bbox linebox, charbox;
	fz_text_block *block;
	fz_text_line *line;
	fz_text_span *span;
	int i, hit_count;

	int x0 = rect.x0;
	int x1 = rect.x1;
	int y0 = rect.y0;
	int y1 = rect.y1;

	hit_count = 0;

	for (block = page->blocks; block < page->blocks + page->len; block++)
	{
		for (line = block->lines; line < block->lines + block->len; line++)
		{
			linebox = fz_empty_bbox;
			for (span = line->spans; span < line->spans + line->len; span++)
			{
				for (i = 0; i < span->len; i++)
				{
					charbox = fz_bbox_covering_rect(span->text[i].bbox);
					if (charbox.x1 >= x0 && charbox.x0 <= x1 && charbox.y1 >= y0 && charbox.y0 <= y1)
					{
						if (charbox.y0 != linebox.y0 || fz_absi(charbox.x0 - linebox.x1) > 5)
						{
							if (!fz_is_empty_bbox(linebox) && hit_count < hit_max)
								hit_bbox[hit_count++] = linebox;
							linebox = charbox;
						}
						else
						{
							linebox = fz_union_bbox(linebox, charbox);
						}
					}
				}
			}
			if (!fz_is_empty_bbox(linebox) && hit_count < hit_max)
				hit_bbox[hit_count++] = linebox;
		}
	}

	return hit_count;
}
Esempio n. 2
0
//sumatrapdf code
int extractText(miniexp_t item, Arraylist list, fz_bbox * target) {
    miniexp_t type = miniexp_car(item);

    if (!miniexp_symbolp(type))
        return 0;

    item = miniexp_cdr(item);

    if (!miniexp_numberp(miniexp_car(item))) return 0;
    int x0 = miniexp_to_int(miniexp_car(item)); item = miniexp_cdr(item);
    if (!miniexp_numberp(miniexp_car(item))) return 0;
    int y0 = miniexp_to_int(miniexp_car(item)); item = miniexp_cdr(item);
    if (!miniexp_numberp(miniexp_car(item))) return 0;
    int x1 = miniexp_to_int(miniexp_car(item)); item = miniexp_cdr(item);
    if (!miniexp_numberp(miniexp_car(item))) return 0;
    int y1 = miniexp_to_int(miniexp_car(item)); item = miniexp_cdr(item);
    //RectI rect = RectI::FromXY(x0, y0, x1, y1);
    fz_bbox rect = {x0 , y0 , x1 , y1};

    miniexp_t str = miniexp_car(item);

    if (miniexp_stringp(str) && !miniexp_cdr(item)) {
        fz_bbox inters = fz_intersect_bbox(rect, *target);
            //LOGI("Start text extraction: rectangle=[%d,%d,%d,%d] %s", rect.x0, rect.y0, rect.x1, rect.y1, content);
        if (!fz_is_empty_bbox(inters)) {
            const char *content = miniexp_to_str(str);

            while (*content) {
                arraylist_add(list, *content++);
            }

    //        if (value) {
    //            size_t len = str::Len(value);
    //            // TODO: split the rectangle into individual parts per glyph
    //            for (size_t i = 0; i < len; i++)
    //                coords.Append(RectI(rect.x, rect.y, rect.dx, rect.dy));
    //            extracted.AppendAndFree(value);
    //        }
            if (miniexp_symbol("word") == type) {
                arraylist_add(list, ' ');
                //coords.Append(RectI(rect.x + rect.dx, rect.y, 2, rect.dy));
            }
            else if (miniexp_symbol("char") != type) {
                arraylist_add(list, '\n');
    //            extracted.Append(lineSep);
    //            for (size_t i = 0; i < str::Len(lineSep); i++)
    //                coords.Append(RectI());
            }
        }
        item = miniexp_cdr(item);
    }

    while (miniexp_consp(str)) {
        extractText(str, list, target);
        item = miniexp_cdr(item);
        str = miniexp_car(item);
    }

    return !item;
}
int
fz_search_text_page(fz_context *ctx, fz_text_page *text, char *needle, fz_bbox *hit_bbox, int hit_max)
{
	int pos, len, i, n, hit_count;

	if (strlen(needle) == 0)
		return 0;

	hit_count = 0;
	len = textlen(text);
	for (pos = 0; pos < len; pos++)
	{
		n = match(text, needle, pos);
		if (n)
		{
			fz_bbox linebox = fz_empty_bbox;
			for (i = 0; i < n; i++)
			{
				fz_bbox charbox = bboxat(text, pos + i);
				if (!fz_is_empty_bbox(charbox))
				{
					if (charbox.y0 != linebox.y0 || fz_absi(charbox.x0 - linebox.x1) > 5)
					{
						if (!fz_is_empty_bbox(linebox) && hit_count < hit_max)
							hit_bbox[hit_count++] = linebox;
						linebox = charbox;
					}
					else
					{
						linebox = fz_union_bbox(linebox, charbox);
					}
				}
			}
			if (!fz_is_empty_bbox(linebox) && hit_count < hit_max)
				hit_bbox[hit_count++] = linebox;
		}
	}

	return hit_count;
}
Esempio n. 4
0
std::shared_ptr<std::vector<std::shared_ptr<RectFloat>>> MuPDFDoc::SearchText(const char* searchText)
{
	fz_text_sheet *sheet = nullptr;
	fz_text_page *text = nullptr;
	fz_device *dev  = nullptr;
	PageCache *pageCache = &m_pages[m_currentPage];
	fz_var(sheet);
	fz_var(text);
	fz_var(dev);
	std::shared_ptr<std::vector<std::shared_ptr<RectFloat>>> hints(new std::vector<std::shared_ptr<RectFloat>>());
	fz_try(m_context)
	{
		int hitCount = 0;
		fz_matrix ctm = CalcConvertMatrix();
		fz_rect mbrect = fz_transform_rect(ctm, pageCache->mediaBox);
		sheet = fz_new_text_sheet(m_context);
		text = fz_new_text_page(m_context, mbrect);
		dev = fz_new_text_device(m_context, sheet, text);
		fz_run_page(m_document, pageCache->page, dev, ctm, nullptr);
		fz_free_device(dev);
		dev = nullptr;
		int len = TextLen(text);
		for (int pos = 0; pos < len; pos++)
		{
			fz_bbox rr = fz_empty_bbox;
			int n = Match(text, searchText, pos);
			for (int i = 0; i < n; i++)
				rr = fz_union_bbox(rr, BBoxCharAt(text, pos + i));

			if (!fz_is_empty_bbox(rr) && hitCount < MAX_SEARCH_HITS)
			{
				hints->push_back(std::shared_ptr<RectFloat>(new RectFloat(rr.x0, rr.y0, rr.x1, rr.y1)));
				if (++hitCount >= MAX_SEARCH_HITS)
					break;
			}
		}
	}
	fz_always(m_context)
	{
		fz_free_text_page(m_context, text);
		fz_free_text_sheet(m_context, sheet);
		fz_free_device(dev);
	}
	fz_catch(m_context)
	{
		return std::shared_ptr<std::vector<std::shared_ptr<RectFloat>>>(nullptr);
	}
	return hints;
}
Esempio n. 5
0
void
fz_execute_display_list(fz_display_list *list, fz_device *dev, fz_matrix top_ctm, fz_bbox scissor)
{
	fz_display_node *node;
	fz_matrix ctm;
	fz_rect rect;
	fz_bbox bbox;
	int clipped = 0;
	int tiled = 0;
	int empty;

	if (!fz_is_infinite_bbox(scissor))
	{
		/* add some fuzz at the edges, as especially glyph rects
		 * are sometimes not actually completely bounding the glyph */
		scissor.x0 -= 20; scissor.y0 -= 20;
		scissor.x1 += 20; scissor.y1 += 20;
	}

	for (node = list->first; node; node = node->next)
	{
		/* cull objects to draw using a quick visibility test */

		if (tiled || node->cmd == FZ_CMD_BEGIN_TILE || node->cmd == FZ_CMD_END_TILE)
		{
			empty = 0;
		}
		else
		{
			bbox = fz_round_rect(fz_transform_rect(top_ctm, node->rect));
			bbox = fz_intersect_bbox(bbox, scissor);
			empty = fz_is_empty_bbox(bbox);
		}

		if (clipped || empty)
		{
			switch (node->cmd)
			{
			case FZ_CMD_CLIP_PATH:
			case FZ_CMD_CLIP_STROKE_PATH:
			case FZ_CMD_CLIP_TEXT:
			case FZ_CMD_CLIP_STROKE_TEXT:
			case FZ_CMD_CLIP_IMAGE_MASK:
			case FZ_CMD_BEGIN_MASK:
			case FZ_CMD_BEGIN_GROUP:
				clipped++;
				continue;
			case FZ_CMD_POP_CLIP:
			case FZ_CMD_END_GROUP:
				if (!clipped)
					goto visible;
				clipped--;
				continue;
			case FZ_CMD_END_MASK:
				if (!clipped)
					goto visible;
				continue;
			default:
				continue;
			}
		}

visible:
		ctm = fz_concat(node->ctm, top_ctm);

		switch (node->cmd)
		{
		case FZ_CMD_FILL_PATH:
			fz_fill_path(dev, node->item.path, node->flag, ctm,
				node->colorspace, node->color, node->alpha);
			break;
		case FZ_CMD_STROKE_PATH:
			fz_stroke_path(dev, node->item.path, node->stroke, ctm,
				node->colorspace, node->color, node->alpha);
			break;
		case FZ_CMD_CLIP_PATH:
		{
			fz_rect trect = fz_transform_rect(top_ctm, node->rect);
			fz_clip_path(dev, node->item.path, &trect, node->flag, ctm);
			break;
		}
		case FZ_CMD_CLIP_STROKE_PATH:
		{
			fz_rect trect = fz_transform_rect(top_ctm, node->rect);
			fz_clip_stroke_path(dev, node->item.path, &trect, node->stroke, ctm);
			break;
		}
		case FZ_CMD_FILL_TEXT:
			fz_fill_text(dev, node->item.text, ctm,
				node->colorspace, node->color, node->alpha);
			break;
		case FZ_CMD_STROKE_TEXT:
			fz_stroke_text(dev, node->item.text, node->stroke, ctm,
				node->colorspace, node->color, node->alpha);
			break;
		case FZ_CMD_CLIP_TEXT:
			fz_clip_text(dev, node->item.text, ctm, node->flag);
			break;
		case FZ_CMD_CLIP_STROKE_TEXT:
			fz_clip_stroke_text(dev, node->item.text, node->stroke, ctm);
			break;
		case FZ_CMD_IGNORE_TEXT:
			fz_ignore_text(dev, node->item.text, ctm);
			break;
		case FZ_CMD_FILL_SHADE:
			fz_fill_shade(dev, node->item.shade, ctm, node->alpha);
			break;
		case FZ_CMD_FILL_IMAGE:
			fz_fill_image(dev, node->item.image, ctm, node->alpha);
			break;
		case FZ_CMD_FILL_IMAGE_MASK:
			fz_fill_image_mask(dev, node->item.image, ctm,
				node->colorspace, node->color, node->alpha);
			break;
		case FZ_CMD_CLIP_IMAGE_MASK:
		{
			fz_rect trect = fz_transform_rect(top_ctm, node->rect);
			fz_clip_image_mask(dev, node->item.image, &trect, ctm);
			break;
		}
		case FZ_CMD_POP_CLIP:
			fz_pop_clip(dev);
			break;
		case FZ_CMD_BEGIN_MASK:
			rect = fz_transform_rect(top_ctm, node->rect);
			fz_begin_mask(dev, rect, node->flag, node->colorspace, node->color);
			break;
		case FZ_CMD_END_MASK:
			fz_end_mask(dev);
			break;
		case FZ_CMD_BEGIN_GROUP:
			rect = fz_transform_rect(top_ctm, node->rect);
			fz_begin_group(dev, rect,
				node->flag & ISOLATED, node->flag & KNOCKOUT,
				node->item.blendmode, node->alpha);
			break;
		case FZ_CMD_END_GROUP:
			fz_end_group(dev);
			break;
		case FZ_CMD_BEGIN_TILE:
			tiled++;
			rect.x0 = node->color[2];
			rect.y0 = node->color[3];
			rect.x1 = node->color[4];
			rect.y1 = node->color[5];
			fz_begin_tile(dev, node->rect, rect,
				node->color[0], node->color[1], ctm);
			break;
		case FZ_CMD_END_TILE:
			tiled--;
			fz_end_tile(dev);
			break;
		}
	}
}
Esempio n. 6
0
void
fz_run_display_list(fz_display_list *list, fz_device *dev, fz_matrix top_ctm, fz_bbox scissor, fz_cookie *cookie)
{
	fz_display_node *node;
	fz_matrix ctm;
	fz_rect rect;
	fz_bbox bbox;
	int clipped = 0;
	int tiled = 0;
	int empty;
	int progress = 0;
	
	//LOGE("Count %d", count);
	if (cookie)
	{
		cookie->progress_max = list->last - list->first;
		cookie->progress = 0;
	}

	for (node = list->first; node; node = node->next)
	{
		/* Check the cookie for aborting */
		if (cookie)
		{
			if (cookie->abort)
				break;
			cookie->progress = progress++;
		}

		/* cull objects to draw using a quick visibility test */

		if (tiled || node->cmd == FZ_CMD_BEGIN_TILE || node->cmd == FZ_CMD_END_TILE)
		{
			empty = 0;
		}
		else
		{
			bbox = fz_bbox_covering_rect(fz_transform_rect(top_ctm, node->rect));
			bbox = fz_intersect_bbox(bbox, scissor);
			empty = fz_is_empty_bbox(bbox);
		}

		if (clipped || empty)
		{
			switch (node->cmd)
			{
			case FZ_CMD_CLIP_PATH:
			case FZ_CMD_CLIP_STROKE_PATH:
			case FZ_CMD_CLIP_STROKE_TEXT:
			case FZ_CMD_CLIP_IMAGE_MASK:
			case FZ_CMD_BEGIN_MASK:
			case FZ_CMD_BEGIN_GROUP:
				clipped++;
				continue;
			case FZ_CMD_CLIP_TEXT:
				/* Accumulated text has no extra pops */
				if (node->flag != 2)
					clipped++;
				continue;
			case FZ_CMD_POP_CLIP:
			case FZ_CMD_END_GROUP:
				if (!clipped)
					goto visible;
				clipped--;
				continue;
			case FZ_CMD_END_MASK:
				if (!clipped)
					goto visible;
				continue;
			default:
				continue;
			}
		}

visible:
		ctm = fz_concat(node->ctm, top_ctm);

		switch (node->cmd)
		{
		case FZ_CMD_FILL_PATH:
			fz_fill_path(dev, node->item.path, node->flag, ctm,
				node->colorspace, node->color, node->alpha);
			break;
		case FZ_CMD_STROKE_PATH:
			fz_stroke_path(dev, node->item.path, node->stroke, ctm,
				node->colorspace, node->color, node->alpha);
			break;
		case FZ_CMD_CLIP_PATH:
		{
			fz_rect trect = fz_transform_rect(top_ctm, node->rect);
			fz_clip_path(dev, node->item.path, &trect, node->flag, ctm);
			break;
		}
		case FZ_CMD_CLIP_STROKE_PATH:
		{
			fz_rect trect = fz_transform_rect(top_ctm, node->rect);
			fz_clip_stroke_path(dev, node->item.path, &trect, node->stroke, ctm);
			break;
		}
		case FZ_CMD_FILL_TEXT:
			fz_fill_text(dev, node->item.text, ctm,
				node->colorspace, node->color, node->alpha);
			break;
		case FZ_CMD_STROKE_TEXT:
			fz_stroke_text(dev, node->item.text, node->stroke, ctm,
				node->colorspace, node->color, node->alpha);
			break;
		case FZ_CMD_CLIP_TEXT:
			fz_clip_text(dev, node->item.text, ctm, node->flag);
			break;
		case FZ_CMD_CLIP_STROKE_TEXT:
			fz_clip_stroke_text(dev, node->item.text, node->stroke, ctm);
			break;
		case FZ_CMD_IGNORE_TEXT:
			fz_ignore_text(dev, node->item.text, ctm);
			break;
		case FZ_CMD_FILL_SHADE:
			fz_fill_shade(dev, node->item.shade, ctm, node->alpha);
			break;
		case FZ_CMD_FILL_IMAGE:
			fz_fill_image(dev, node->item.image, ctm, node->alpha);
			break;
		case FZ_CMD_FILL_IMAGE_MASK:
			fz_fill_image_mask(dev, node->item.image, ctm,
				node->colorspace, node->color, node->alpha);
			break;
		case FZ_CMD_CLIP_IMAGE_MASK:
		{
			fz_rect trect = fz_transform_rect(top_ctm, node->rect);
			fz_clip_image_mask(dev, node->item.image, &trect, ctm);
			break;
		}
		case FZ_CMD_POP_CLIP:
			fz_pop_clip(dev);
			break;
		case FZ_CMD_BEGIN_MASK:
			rect = fz_transform_rect(top_ctm, node->rect);
			fz_begin_mask(dev, rect, node->flag, node->colorspace, node->color);
			break;
		case FZ_CMD_END_MASK:
			fz_end_mask(dev);
			break;
		case FZ_CMD_BEGIN_GROUP:
			rect = fz_transform_rect(top_ctm, node->rect);
			fz_begin_group(dev, rect,
				(node->flag & ISOLATED) != 0, (node->flag & KNOCKOUT) != 0,
				node->item.blendmode, node->alpha);
			break;
		case FZ_CMD_END_GROUP:
			fz_end_group(dev);
			break;
		case FZ_CMD_BEGIN_TILE:
			tiled++;
			rect.x0 = node->color[2];
			rect.y0 = node->color[3];
			rect.x1 = node->color[4];
			rect.y1 = node->color[5];
			fz_begin_tile(dev, node->rect, rect,
				node->color[0], node->color[1], ctm);
			break;
		case FZ_CMD_END_TILE:
			tiled--;
			fz_end_tile(dev);
			break;
		}
	}
	//free(node_array);
}
Esempio n. 7
0
JNIEXPORT jobjectArray JNICALL
Java_com_artifex_mupdf_MuPDFCore_searchPage(JNIEnv * env, jobject thiz, jstring jtext)
{
	jclass         rectClass;
	jmethodID      ctor;
	jobjectArray   arr;
	jobject        rect;
	fz_text_sheet *sheet = NULL;
	fz_text_page  *text = NULL;
	fz_device     *dev  = NULL;
	float          zoom;
	fz_matrix      ctm;
	int            pos;
	int            len;
	int            i, n;
	int            hit_count = 0;
	const char    *str;
	page_cache    *pc = &pages[current];

	rectClass = (*env)->FindClass(env, "android/graphics/RectF");
	if (rectClass == NULL) return NULL;
	ctor = (*env)->GetMethodID(env, rectClass, "<init>", "(FFFF)V");
	if (ctor == NULL) return NULL;
	str = (*env)->GetStringUTFChars(env, jtext, NULL);
	if (str == NULL) return NULL;

	fz_var(sheet);
	fz_var(text);
	fz_var(dev);

	fz_try(ctx)
	{
		fz_rect rect;

		if (hit_bbox == NULL)
			hit_bbox = fz_malloc_array(ctx, MAX_SEARCH_HITS, sizeof(*hit_bbox));

		zoom = resolution / 72;
		ctm = fz_scale(zoom, zoom);
		rect = fz_transform_rect(ctm, pc->media_box);
		sheet = fz_new_text_sheet(ctx);
		text = fz_new_text_page(ctx, rect);
		dev  = fz_new_text_device(ctx, sheet, text);
		fz_run_page(doc, pc->page, dev, ctm, NULL);
		fz_free_device(dev);
		dev = NULL;

		len = textlen(text);
		for (pos = 0; pos < len; pos++)
		{
			fz_bbox rr = fz_empty_bbox;
			n = match(text, str, pos);
			for (i = 0; i < n; i++)
				rr = fz_union_bbox(rr, bboxcharat(text, pos + i));

			if (!fz_is_empty_bbox(rr) && hit_count < MAX_SEARCH_HITS)
				hit_bbox[hit_count++] = rr;
		}
	}
	fz_always(ctx)
	{
		fz_free_text_page(ctx, text);
		fz_free_text_sheet(ctx, sheet);
		fz_free_device(dev);
	}
	fz_catch(ctx)
	{
		jclass cls;
		(*env)->ReleaseStringUTFChars(env, jtext, str);
		cls = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
		if (cls != NULL)
			(*env)->ThrowNew(env, cls, "Out of memory in MuPDFCore_searchPage");
		(*env)->DeleteLocalRef(env, cls);

		return NULL;
	}

	(*env)->ReleaseStringUTFChars(env, jtext, str);

	arr = (*env)->NewObjectArray(env,
					hit_count,
					rectClass,
					NULL);
	if (arr == NULL) return NULL;

	for (i = 0; i < hit_count; i++) {
		rect = (*env)->NewObject(env, rectClass, ctor,
				(float) (hit_bbox[i].x0),
				(float) (hit_bbox[i].y0),
				(float) (hit_bbox[i].x1),
				(float) (hit_bbox[i].y1));
		if (rect == NULL)
			return NULL;
		(*env)->SetObjectArrayElement(env, arr, i, rect);
		(*env)->DeleteLocalRef(env, rect);
	}

	return arr;
}
Esempio n. 8
0
JNIEXPORT jboolean JNICALL
Java_com_artifex_mupdf_MuPDFCore_updatePageInternal(JNIEnv *env, jobject thiz, jobject bitmap, int page,
		int pageW, int pageH, int patchX, int patchY, int patchW, int patchH)
{
	AndroidBitmapInfo info;
	void *pixels;
	int ret;
	fz_device *dev = NULL;
	float zoom;
	fz_matrix ctm;
	fz_bbox bbox;
	fz_pixmap *pix = NULL;
	float xscale, yscale;
	fz_bbox rect;
	fz_interactive *idoc;
	page_cache *pc = NULL;
	int hq = (patchW < pageW || patchH < pageH);
	int i;

	for (i = 0; i < NUM_CACHE; i++)
	{
		if (pages[i].page != NULL && pages[i].number == page)
		{
			pc = &pages[i];
			break;
		}
	}

	if (pc == NULL || (hq && pc->hq_page == NULL))
	{
		Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(env, thiz, page);
		return Java_com_artifex_mupdf_MuPDFCore_drawPage(env, thiz, bitmap, pageW, pageH, patchX, patchY, patchW, patchH);
	}

	idoc = fz_interact(doc);

	fz_var(pix);
	fz_var(dev);

	LOGI("In native method\n");
	if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
		LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
		return 0;
	}

	LOGI("Checking format\n");
	if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
		LOGE("Bitmap format is not RGBA_8888 !");
		return 0;
	}

	LOGI("locking pixels\n");
	if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
		LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
		return 0;
	}

	/* Call mupdf to render display list to screen */
	LOGE("Rendering page(%d)=%dx%d patch=[%d,%d,%d,%d]",
			pc->number, pageW, pageH, patchX, patchY, patchW, patchH);

	fz_try(ctx)
	{
		fz_annot *annot;
		// Unimportant which page object we use for rendering but we
		// must use the correct one for calculating updates
		fz_page *page = hq ? pc->hq_page : pc->page;

		fz_update_page(idoc, page);

		if (pc->page_list == NULL)
		{
			/* Render to list */
			pc->page_list = fz_new_display_list(ctx);
			dev = fz_new_list_device(ctx, pc->page_list);
			fz_run_page_contents(doc, page, dev, fz_identity, NULL);
		}

		if (pc->annot_list == NULL) {
			if (dev) {
				fz_free_device(dev);
				dev = NULL;
			}
			pc->annot_list = fz_new_display_list(ctx);
			dev = fz_new_list_device(ctx, pc->annot_list);
			for (annot = fz_first_annot(doc, page); annot; annot = fz_next_annot(doc, annot))
				fz_run_annot(doc, page, annot, dev, fz_identity, NULL);
		}

		rect.x0 = patchX;
		rect.y0 = patchY;
		rect.x1 = patchX + patchW;
		rect.y1 = patchY + patchH;
		pix = fz_new_pixmap_with_bbox_and_data(ctx, colorspace, rect, pixels);

		zoom = resolution / 72;
		ctm = fz_scale(zoom, zoom);
		bbox = fz_round_rect(fz_transform_rect(ctm, pc->media_box));
		/* Now, adjust ctm so that it would give the correct page width
		 * heights. */
		xscale = (float)pageW/(float)(bbox.x1-bbox.x0);
		yscale = (float)pageH/(float)(bbox.y1-bbox.y0);
		ctm = fz_concat(ctm, fz_scale(xscale, yscale));
		bbox = fz_round_rect(fz_transform_rect(ctm, pc->media_box));

		LOGI("Start polling for updates");
		while ((annot = fz_poll_changed_annot(idoc, page)) != NULL)
		{
			fz_bbox abox = fz_round_rect(fz_transform_rect(ctm, fz_bound_annot(doc, annot)));
			abox = fz_intersect_bbox(abox, rect);

			LOGI("Update rectanglefor %s - (%d, %d, %d, %d)", widget_type_string(fz_widget_get_type((fz_widget*)annot)),
					abox.x0, abox.y0, abox.x1, abox.y1);
			if (!fz_is_empty_bbox(abox))
			{
				LOGI("And it isn't empty");
				fz_clear_pixmap_rect_with_value(ctx, pix, 0xff, abox);
				dev = fz_new_draw_device_with_bbox(ctx, pix, abox);
				if (pc->page_list)
					fz_run_display_list(pc->page_list, dev, ctm, abox, NULL);
				if (pc->annot_list)
					fz_run_display_list(pc->annot_list, dev, ctm, abox, NULL);
				fz_free_device(dev);
				dev = NULL;
			}
		}
		LOGI("Done polling for updates");

		LOGE("Rendered");
	}
	fz_catch(ctx)
	{
		fz_free_device(dev);
		LOGE("Render failed");
	}

	fz_drop_pixmap(ctx, pix);
	AndroidBitmap_unlockPixels(env, bitmap);

	return 1;
}
Esempio n. 9
0
HRESULT MuPDFDoc::UpdatePage(int pageNumber, unsigned char *bitmap, int x, int y, int width, int height, bool invert)
{
	int index = FindPageInCache(pageNumber);
	if (index < 0)
	{
		//TODO: get rid of this side effect!!!
		HRESULT result = GotoPage(pageNumber);
		if (FAILED(result))
		{
			return result;
		}
		return DrawPage(bitmap, x, y, width, height, invert);
	}
	fz_device *dev = nullptr;
	fz_pixmap *pixmap = nullptr;
	fz_var(dev);
	fz_var(pixmap);
	PageCache *pageCache = &m_pages[m_currentPage];
	fz_try(m_context)
	{
		fz_interactive *idoc = fz_interact(m_document);
		// Call fz_update_page now to ensure future calls yield the
		// changes from the current state
		if (idoc)
			fz_update_page(idoc, pageCache->page);

		if (!pageCache->pageList)
		{
			/* Render to list */
			pageCache->pageList = fz_new_display_list(m_context);
			dev = fz_new_list_device(m_context, pageCache->pageList);
			fz_run_page_contents(m_document, pageCache->page, dev, fz_identity, nullptr);
		}
		if (!pageCache->annotList)
		{
			if (dev)
			{
				fz_free_device(dev);
				dev = nullptr;
			}
			pageCache->annotList = fz_new_display_list(m_context);
			dev = fz_new_list_device(m_context, pageCache->annotList);
			for (fz_annot *annot = fz_first_annot(m_document, pageCache->page); annot; annot = fz_next_annot(m_document, annot))
				fz_run_annot(m_document, pageCache->page, annot, dev, fz_identity, nullptr);
		}
		fz_bbox rect;
		rect.x0 = x;
		rect.y0 = y;
		rect.x1 = x + width;
		rect.y1 = y + height;
		pixmap = fz_new_pixmap_with_bbox_and_data(m_context, fz_device_bgr, rect, bitmap);
		//
		fz_matrix ctm = CalcConvertMatrix();
		fz_bbox bbox = fz_round_rect(fz_transform_rect(ctm, pageCache->mediaBox));
		/* Now, adjust ctm so that it would give the correct page width
		 * heights. */
		float xscale = (float)width/(float)(bbox.x1-bbox.x0);
		float yscale = (float)height/(float)(bbox.y1-bbox.y0);
		ctm = fz_concat(ctm, fz_scale(xscale, yscale));
		bbox = fz_round_rect(fz_transform_rect(ctm, pageCache->mediaBox));
		if (dev)
		{
			fz_free_device(dev);
			dev = nullptr;
		}
		fz_annot *annot;
		while (idoc && (annot = fz_poll_changed_annot(idoc, pageCache->page)))
		{
			fz_bbox abox = fz_round_rect(fz_transform_rect(ctm, fz_bound_annot(m_document, annot)));
			abox = fz_intersect_bbox(abox, rect);

			if (!fz_is_empty_bbox(abox))
			{
				fz_clear_pixmap_rect_with_value(m_context, pixmap, 0xff, abox);
				dev = fz_new_draw_device_with_bbox(m_context, pixmap, abox);
				if (pageCache->pageList)
					fz_run_display_list(pageCache->pageList, dev, ctm, abox, nullptr);
				if (pageCache->annotList)
					fz_run_display_list(pageCache->annotList, dev, ctm, abox, nullptr);
				fz_free_device(dev);
				dev = nullptr;
				if (invert)
					fz_invert_pixmap_rect(pixmap, abox);
			}
		}
	}
	fz_always(m_context)
	{
		if (dev)
		{
			fz_free_device(dev);
			dev = nullptr;
		}
		if (pixmap)
		{
			fz_drop_pixmap(m_context, pixmap);
		}
	}
	fz_catch(m_context)
	{
		return E_FAIL;
	}
	return S_OK;
}