Beispiel #1
0
/* This function completes a rendering job.
 *
 * The thread is added to the pool of idle threads.
 */
static void finish_page_render(struct least_thread *render)
{
    union _dispose_volatile {
        volatile fz_pixmap *volatile_pixmap;
        fz_pixmap *pixmap;
    } d;

    d.volatile_pixmap = render->pixmap;

    /* XXX Error handling ? */
    if (render->pre_refresh)
        printf("finish_page: Discarding pre-refresh render "
            "of page %d by thread %d\n", render->pagenum, render->id);
    else {
        /* Page is complete and no longer rendering */
        pages[render->pagenum].rendering = 0;

        /* Convert to texture */
        pages[render->pagenum].texture = pixmap_to_texture(
            (void*)fz_pixmap_samples(render->context, d.pixmap),
            fz_pixmap_width(render->context, d.pixmap),
            fz_pixmap_height(render->context, d.pixmap), 0, 0);
    }

    /* XXX Using the threads context might not be a gr8 idea */
    fz_drop_pixmap(render->context, d.pixmap);

    /* Place thread into idle pool */
    idle_threads[idle_thread_count++] = render;
}
Beispiel #2
0
	QImage Document::RenderPage (int num, double xRes, double yRes)
	{
		auto page = WrapPage (pdf_load_page (MuDoc_, num), MuDoc_);
		if (!page)
			return QImage ();

#if MUPDF_VERSION < 0x0102
		const auto& rect = pdf_bound_page (MuDoc_, page.get ());
#else
		fz_rect rect;
		pdf_bound_page (MuDoc_, page.get (), &rect);
#endif

		auto px = fz_new_pixmap (MuCtx_, fz_device_bgr, xRes * (rect.x1 - rect.x0), yRes * (rect.y1 - rect.y0));
		fz_clear_pixmap (MuCtx_, px);
		auto dev = fz_new_draw_device (MuCtx_, px);
#if MUPDF_VERSION < 0x0102
		pdf_run_page (MuDoc_, page.get (), dev, fz_scale (xRes, yRes), NULL);
#else
		fz_matrix matrix;
		pdf_run_page (MuDoc_, page.get (), dev, fz_scale (&matrix, xRes, yRes), NULL);
#endif
		fz_free_device (dev);

		const int pxWidth = fz_pixmap_width (MuCtx_, px);
		const int pxHeight = fz_pixmap_height (MuCtx_, px);

		auto samples = fz_pixmap_samples (MuCtx_, px);

		QImage temp (samples, pxWidth, pxHeight, QImage::Format_ARGB32);
		QImage img (QSize (pxWidth, pxHeight), QImage::Format_ARGB32);

		for (int y = 0; y < pxHeight; ++y)
		{
			auto target = reinterpret_cast<QRgb*> (img.scanLine (y));
			const auto source = reinterpret_cast<QRgb*> (temp.scanLine (y));
			std::memcpy (target, source, sizeof (source [0]) * pxWidth);
		}
		fz_drop_pixmap (MuCtx_, px);

		temp = QImage (QSize (pxWidth, pxHeight), QImage::Format_ARGB32);

		QPainter p;
		p.begin (&temp);
		p.fillRect (QRect (QPoint (0, 0), temp.size ()), Qt::white);
		p.drawImage (0, 0, img);
		p.end ();
		return temp;
	}
Beispiel #3
0
void PDFDocument::Render(
    Document::PixelWriter* pw, int page, float zoom, int rotation) {
  assert((page >= 0) && (page < GetNumPages()));

  std::unique_lock<std::mutex> lock(_render_mutex);

  // 1. Init MuPDF structures.
  const fz_matrix& m = Transform(zoom, rotation);
  pdf_page* page_struct = GetPage(page);
  const fz_irect& bbox = GetBoundingBox(page_struct, m);
  fz_pixmap* pixmap = fz_new_pixmap_with_bbox(
      _fz_context, fz_device_rgb(_fz_context), FZ_OBJ(bbox), nullptr, 1);
  fz_device* dev = fz_new_draw_device(_fz_context, FZ_OBJ(fz_identity), pixmap);

  // 2. Render page.
  fz_clear_pixmap_with_value(_fz_context, pixmap, 0xff);
  pdf_run_page(
      _fz_context, _pdf_document, page_struct, dev, FZ_OBJ(m), nullptr);

  // 3. Write pixmap to buffer. The page is vertically divided into n equal
  // stripes, each copied to pw by one thread.
  assert(fz_pixmap_components(_fz_context, pixmap) == 4);
  uint8_t* buffer =
      reinterpret_cast<uint8_t*>(fz_pixmap_samples(_fz_context, pixmap));
  const int num_cols = fz_pixmap_width(_fz_context, pixmap);
  const int num_rows = fz_pixmap_height(_fz_context, pixmap);
  ExecuteInParallel([=](int num_threads, int i) {
    const int num_rows_per_thread = num_rows / num_threads;
    const int y_begin = i * num_rows_per_thread;
    const int y_end =
        (i == num_threads - 1) ? num_rows : (i + 1) * num_rows_per_thread;
    uint8_t* p = buffer + y_begin * num_cols * 4;
    for (int y = y_begin; y < y_end; ++y) {
      for (int x = 0; x < num_cols; ++x) {
        pw->Write(x, y, p[0], p[1], p[2]);
        p += 4;
      }
    }
  });

  // 4. Clean up.
  fz_close_device(_fz_context, dev);
  fz_drop_device(_fz_context, dev);
  fz_drop_pixmap(_fz_context, pixmap);
}
Beispiel #4
0
static int bmpmupdf_pixmap_to_bmp(WILLUSBITMAP *bmp,fz_context *ctx,fz_pixmap *pixmap)

    {
	unsigned char *p;
	int ncomp,i,row,col;

    bmp->width=fz_pixmap_width(ctx,pixmap);
    bmp->height=fz_pixmap_height(ctx,pixmap);
    ncomp=fz_pixmap_components(ctx,pixmap);
    /* Has to be 8-bit or RGB */
	if (ncomp != 2 && ncomp != 4)
		return(-1);
    bmp->bpp=(ncomp==2) ? 8 : 24;
    bmp_alloc(bmp);
    if (ncomp==2)
        for (i=0;i<256;i++)
            bmp->red[i]=bmp->green[i]=bmp->blue[i]=i;
	p = fz_pixmap_samples(ctx,pixmap);
    if (ncomp==1)
        for (row=0;row<bmp->height;row++)
            {
            unsigned char *dest;
            dest=bmp_rowptr_from_top(bmp,row);
            memcpy(dest,p,bmp->width);
            p+=bmp->width;
            }
    else if (ncomp==2)
        for (row=0;row<bmp->height;row++)
            {
            unsigned char *dest;
            dest=bmp_rowptr_from_top(bmp,row);
            for (col=0;col<bmp->width;col++,dest++,p+=2)
                dest[0]=p[0];
            }
    else
        for (row=0;row<bmp->height;row++)
            {
            unsigned char *dest;
            dest=bmp_rowptr_from_top(bmp,row);
            for (col=0;col<bmp->width;col++,dest+=ncomp-1,p+=ncomp)
                memcpy(dest,p,ncomp-1);
            }
	return(0);
    }
Beispiel #5
0
static int page_to_texture(fz_context *context, fz_document *doc, int pagenum) {
    fz_pixmap *image;

    /* Since this function is only called initially, this is an excellent place
     * to lock the window height/width.
     * Afterwards this can be changed using the 'F5' key.
     */
    lw = w;
    lh = h;

    /* Convert page to pixmap */
    image = page_to_pixmap(context, doc, pagenum);

    /* Convert to texture here */
    pages[pagenum].texture = pixmap_to_texture((void*)fz_pixmap_samples(context, image),
            fz_pixmap_width(context, image),
            fz_pixmap_height(context, image), 0, 0);

    fz_drop_pixmap(context, image);

    return pages[pagenum].texture;
}
Beispiel #6
0
static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
{
	fz_page *page;
	fz_display_list *list = NULL;
	fz_device *dev = NULL;
	int start;
	fz_cookie cookie = { 0 };

	fz_var(list);
	fz_var(dev);

	fz_try(ctx)
	{
		page = fz_load_page(doc, pagenum - 1);
	}
	fz_catch(ctx)
	{
		fz_throw(ctx, "cannot load page %d in file '%s'", pagenum, filename);
	}

	float zoom;
	fz_matrix ctm;
	fz_rect bounds, bounds2;
	fz_bbox bbox;
	fz_pixmap *pix = NULL;
	int w, h;

	fz_var(pix);

	bounds = fz_bound_page(doc, page);
	zoom = resolution / 72;
	ctm = fz_scale(zoom, zoom);
	ctm = fz_concat(ctm, fz_rotate(rotation));
	bounds2 = fz_transform_rect(ctm, bounds);
	bbox = fz_round_rect(bounds2);
	/* Make local copies of our width/height */
	w = width;
	h = height;
	/* If a resolution is specified, check to see whether w/h are
	 * exceeded; if not, unset them. */
	if (res_specified)
	{
		int t;
		t = bbox.x1 - bbox.x0;
		if (w && t <= w)
			w = 0;
		t = bbox.y1 - bbox.y0;
		if (h && t <= h)
			h = 0;
	}
	/* Now w or h will be 0 unless then need to be enforced. */
	if (w || h)
	{
		float scalex = w/(bounds2.x1-bounds2.x0);
		float scaley = h/(bounds2.y1-bounds2.y0);

		if (fit)
		{
			if (w == 0)
				scalex = 1.0f;
			if (h == 0)
				scaley = 1.0f;
		}
		else
		{
			if (w == 0)
				scalex = scaley;
			if (h == 0)
				scaley = scalex;
		}
		if (!fit)
		{
			if (scalex > scaley)
				scalex = scaley;
			else
				scaley = scalex;
		}
		ctm = fz_concat(ctm, fz_scale(scalex, scaley));
		bounds2 = fz_transform_rect(ctm, bounds);
	}
	bbox = fz_round_rect(bounds2);

	/* TODO: banded rendering and multi-page ppm */

	fz_try(ctx)
	{
		pix = fz_new_pixmap_with_bbox(ctx, colorspace, bbox);

		fz_clear_pixmap_with_value(ctx, pix, 255);

		dev = fz_new_draw_device(ctx, pix);
		if (list)
			fz_run_display_list(list, dev, ctm, bbox, &cookie);
		else
			fz_run_page(doc, page, dev, ctm, &cookie);
		fz_free_device(dev);
		dev = NULL;

		int size = fz_pixmap_height(ctx, pix) * fz_pixmap_width(ctx, pix);
		inplace_reorder(fz_pixmap_samples(ctx, pix), size);
		size_t x_offset = (width - fz_pixmap_width(ctx, pix)) / 2;
		size_t y_offset = (height - fz_pixmap_height(ctx, pix)) / 2;;
		if (toggle_decors) {
			x_offset += decor_left_width;
			y_offset += decor_top_height;
		}
		for (int i = 0; i < fz_pixmap_height(ctx, pix); ++i) {
			memcpy(&GFX(gfx_ctx, x_offset, y_offset + i), &fz_pixmap_samples(ctx, pix)[fz_pixmap_width(ctx, pix) * i * 4], fz_pixmap_width(ctx, pix) * 4);
		}

	}
	fz_always(ctx)
	{
		fz_free_device(dev);
		dev = NULL;
		fz_drop_pixmap(ctx, pix);
	}
	fz_catch(ctx)
	{
		fz_free_display_list(ctx, list);
		fz_free_page(doc, page);
		fz_rethrow(ctx);
	}

	if (list)
		fz_free_display_list(ctx, list);

	fz_free_page(doc, page);

	fz_flush_warnings(ctx);

	if (cookie.errors)
		errored = 1;
}
Beispiel #7
0
void winblit()
{
	int image_w = fz_pixmap_width(gapp.ctx, gapp.image);
	int image_h = fz_pixmap_height(gapp.ctx, gapp.image);
	int image_n = fz_pixmap_components(gapp.ctx, gapp.image);
	unsigned char *samples = fz_pixmap_samples(gapp.ctx, gapp.image);
	int x0 = gapp.panx;
	int y0 = gapp.pany;
	int x1 = gapp.panx + image_w;
	int y1 = gapp.pany + image_h;
	RECT r;

	if (gapp.image)
	{
		if (gapp.iscopying || justcopied)
		{
			pdfapp_invert(&gapp, &gapp.selr);
			justcopied = 1;
		}

		pdfapp_inverthit(&gapp);

		dibinf->bmiHeader.biWidth = image_w;
		dibinf->bmiHeader.biHeight = -image_h;
		dibinf->bmiHeader.biSizeImage = image_h * 4;

		if (image_n == 2)
		{
			int i = image_w * image_h;
			unsigned char *color = malloc(i*4);
			unsigned char *s = samples;
			unsigned char *d = color;
			for (; i > 0 ; i--)
			{
				d[2] = d[1] = d[0] = *s++;
				d[3] = *s++;
				d += 4;
			}
			SetDIBitsToDevice(hdc,
				gapp.panx, gapp.pany, image_w, image_h,
				0, 0, 0, image_h, color,
				dibinf, DIB_RGB_COLORS);
			free(color);
		}
		if (image_n == 4)
		{
			SetDIBitsToDevice(hdc,
				gapp.panx, gapp.pany, image_w, image_h,
				0, 0, 0, image_h, samples,
				dibinf, DIB_RGB_COLORS);
		}

		pdfapp_inverthit(&gapp);

		if (gapp.iscopying || justcopied)
		{
			pdfapp_invert(&gapp, &gapp.selr);
			justcopied = 1;
		}
	}

	/* Grey background */
	r.top = 0; r.bottom = gapp.winh;
	r.left = 0; r.right = x0;
	FillRect(hdc, &r, bgbrush);
	r.left = x1; r.right = gapp.winw;
	FillRect(hdc, &r, bgbrush);
	r.left = 0; r.right = gapp.winw;
	r.top = 0; r.bottom = y0;
	FillRect(hdc, &r, bgbrush);
	r.top = y1; r.bottom = gapp.winh;
	FillRect(hdc, &r, bgbrush);

	/* Drop shadow */
	r.left = x0 + 2;
	r.right = x1 + 2;
	r.top = y1;
	r.bottom = y1 + 2;
	FillRect(hdc, &r, shbrush);
	r.left = x1;
	r.right = x1 + 2;
	r.top = y0 + 2;
	r.bottom = y1;
	FillRect(hdc, &r, shbrush);

	winblitsearch();
}
Beispiel #8
0
static void winblit(pdfapp_t *app)
{
	int image_w = fz_pixmap_width(gapp.ctx, gapp.image);
	int image_h = fz_pixmap_height(gapp.ctx, gapp.image);
	int image_n = fz_pixmap_components(gapp.ctx, gapp.image);
	unsigned char *image_samples = fz_pixmap_samples(gapp.ctx, gapp.image);
	int x0 = gapp.panx;
	int y0 = gapp.pany;
	int x1 = gapp.panx + image_w;
	int y1 = gapp.pany + image_h;

	XSetForeground(xdpy, xgc, xbgcolor.pixel);
	fillrect(0, 0, x0, gapp.winh);
	fillrect(x1, 0, gapp.winw - x1, gapp.winh);
	fillrect(0, 0, gapp.winw, y0);
	fillrect(0, y1, gapp.winw, gapp.winh - y1);

	XSetForeground(xdpy, xgc, xshcolor.pixel);
	fillrect(x0+2, y1, image_w, 2);
	fillrect(x1, y0+2, 2, image_h);

	if (gapp.iscopying || justcopied)
	{
		pdfapp_invert(&gapp, &gapp.selr);
		justcopied = 1;
	}

	pdfapp_inverthit(&gapp);

	if (image_n == 4)
		ximage_blit(xwin, xgc,
			x0, y0,
			image_samples,
			0, 0,
			image_w,
			image_h,
			image_w * image_n);
	else if (image_n == 2)
	{
		int i = image_w*image_h;
		unsigned char *color = malloc(i*4);
		if (color)
		{
			unsigned char *s = image_samples;
			unsigned char *d = color;
			for (; i > 0 ; i--)
			{
				d[2] = d[1] = d[0] = *s++;
				d[3] = *s++;
				d += 4;
			}
			ximage_blit(xwin, xgc,
				x0, y0,
				color,
				0, 0,
				image_w,
				image_h,
				image_w * 4);
			free(color);
		}
	}

	pdfapp_inverthit(&gapp);

	if (gapp.iscopying || justcopied)
	{
		pdfapp_invert(&gapp, &gapp.selr);
		justcopied = 1;
	}

	winblitsearch(app);

	if (showingpage)
	{
		char buf[42];
		snprintf(buf, sizeof buf, "Page %d/%d", gapp.pageno, gapp.pagecount);
		windrawstringxor(&gapp, 10, 20, buf);
	}
}
Beispiel #9
0
QImage Pdf::page(int i)
      {
      fz_page* page = fz_load_page(doc, i);
      if (page == 0) {
            printf("cannot load page %d\n", i);
            return QImage();
            }
      static const float resolution = 300.0;
      const float zoom = resolution / 72.0;

      fz_rect bounds = fz_bound_page(doc, page);
      fz_matrix ctm  = fz_scale(zoom, zoom);
      fz_bbox bbox   = fz_round_rect(fz_transform_rect(ctm, bounds));
      fz_pixmap* pix = fz_new_pixmap_with_bbox(ctx, fz_device_gray, bbox);

      fz_clear_pixmap_with_value(ctx, pix, 255);
      fz_device* dev = fz_new_draw_device(ctx, pix);
      fz_run_page(doc, page, dev, ctm, NULL);
      fz_free_device(dev);
      dev = NULL;

      int w = fz_pixmap_width(ctx, pix);
      int h = fz_pixmap_height(ctx, pix);
      if (fz_pixmap_components(ctx, pix) != 2) {
            printf("omg: pixmap not bw? %d\n", fz_pixmap_components(ctx, pix));
            return QImage();
            }

      QImage image(w, h, QImage::Format_MonoLSB);
      QVector<QRgb> ct(2);
      ct[0] = qRgb(255, 255, 255);
      ct[1] = qRgb(0, 0, 0);
      image.setColorTable(ct);

      uchar* s   = fz_pixmap_samples(ctx, pix);
      int bytes  = w / 8;
      int bits   = w % 8;
      for (int line = 0; line < h; ++line) {
            uchar* d = image.scanLine(line);
            for (int col = 0; col < bytes; ++col) {
                  uchar data = 0;
                  for (int i = 0; i < 8; ++i) {
                        uchar v = *s;
                        s += 2;
                        data >>= 1;
                        if (v < 128) {            // convert grayscale to bw
                              data |= 0x80;
                              }
                        }
                  *d++ = data;
                  }
            uchar data = 0;
            for (int col = 0; col < bits; ++col) {
                  uchar v = *s;
                  s += 2;
                  data >>= 1;
                  if (v < 128)
                        data |= 0x80;
                  }
            }
      fz_drop_pixmap(ctx, pix);
      return image;
      }
Beispiel #10
0
cairo_surface_t*
pdf_page_image_get_cairo(zathura_page_t* page, void* data,
    zathura_image_t* image, zathura_error_t* error)
{
  mupdf_page_t* mupdf_page = data;

  if (page == NULL || mupdf_page == NULL || image == NULL || image->data == NULL) {
    if (error != NULL) {
      *error = ZATHURA_ERROR_INVALID_ARGUMENTS;
    }
    goto error_ret;
  }

  fz_image* mupdf_image = (fz_image*) image->data;

  fz_pixmap* pixmap = NULL;
  cairo_surface_t* surface = NULL;

  pixmap = fz_get_pixmap_from_image(mupdf_page->ctx, mupdf_image, NULL, NULL, 0, 0);
  if (pixmap == NULL) {
    goto error_free;
  }

  surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, mupdf_image->w, mupdf_image->h);
  if (surface == NULL) {
    goto error_free;
  }

  unsigned char* surface_data = cairo_image_surface_get_data(surface);
  int rowstride = cairo_image_surface_get_stride(surface);

  unsigned char* s = fz_pixmap_samples(mupdf_page->ctx, pixmap);
  unsigned int n   = fz_pixmap_components(mupdf_page->ctx, pixmap);

  const int height = fz_pixmap_height(mupdf_page->ctx, pixmap);
  const int width  = fz_pixmap_width(mupdf_page->ctx, pixmap);
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      guchar* p = surface_data + y * rowstride + x * 4;

      // RGB
      if (n == 4) {
        p[0] = s[2];
        p[1] = s[1];
        p[2] = s[0];
      // Gray-scale or mask
      } else {
        p[0] = s[0];
        p[1] = s[0];
        p[2] = s[0];
      }
      s += n;
    }
  }

  fz_drop_pixmap(mupdf_page->ctx, pixmap);

  return surface;

error_free:

  if (pixmap != NULL) {
    fz_drop_pixmap(mupdf_page->ctx, pixmap);
  }

  if (surface != NULL) {
    cairo_surface_destroy(surface);
  }

error_ret:

  return NULL;
}