Пример #1
0
static void vg_copy_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch)
{
   vg_t *vg = (vg_t*)data;

   if (vg->mEglImageBuf)
   {
      EGLImageKHR img = 0;
      bool new_egl = vg->driver->write_egl_image(frame, width, height, pitch, (vg->mTexType == VG_sXRGB_8888), 0, &img);
      rarch_assert(img != EGL_NO_IMAGE_KHR);

      if (new_egl)
      {
         vgDestroyImage(vg->mImage);
         vg->mImage = pvgCreateEGLImageTargetKHR((VGeglImageKHR) img);
         if (!vg->mImage)
         {
            RARCH_ERR("[VG:EGLImage] Error creating image: %08x\n", vgGetError());
            exit(2);
         }
         vg->last_egl_image = img;
      }
   }
   else
   {
      vgImageSubData(vg->mImage, frame, pitch, vg->mTexType, 0, 0, width, height);
   }
}
Пример #2
0
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
{
   bool ret = false;

   if (index >= MAX_EGLIMAGE_TEXTURES)
   {
      *image_handle = NULL;
      return false;
   }

   eglBindAPI(EGL_OPENVG_API);
   eglMakeCurrent(g_egl_dpy, g_pbuff_surf, g_pbuff_surf, g_eglimage_ctx);

   if (!eglBuffer[index] || !g_egl_vgimage[index])
   {
      g_egl_vgimage[index] = vgCreateImage(rgb32 ? VG_sXRGB_8888 : VG_sRGB_565, g_egl_res, g_egl_res, VG_IMAGE_QUALITY_NONANTIALIASED);
      eglBuffer[index] = peglCreateImageKHR(g_egl_dpy, g_eglimage_ctx, EGL_VG_PARENT_IMAGE_KHR, (EGLClientBuffer)g_egl_vgimage[index], NULL);
      ret = true;
   }

   vgImageSubData(g_egl_vgimage[index], frame, pitch, (rgb32 ? VG_sXRGB_8888 : VG_sRGB_565), 0, 0, width, height);
   *image_handle = eglBuffer[index];

   gfx_ctx_bind_api(g_api);
   eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx);

   return ret;
}
Пример #3
0
static bool rpi_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg)
{
   rpi_t *rpi = (rpi_t*)data;

   if (width != rpi->mRenderWidth || height != rpi->mRenderHeight)
   {
      rpi->mRenderWidth = width;
      rpi->mRenderHeight = height;
      rpi_calculate_quad(rpi);
      vguComputeWarpQuadToQuad(
         rpi->x1, rpi->y1, rpi->x2, rpi->y1, rpi->x2, rpi->y2, rpi->x1, rpi->y2,
         // needs to be flipped, Khronos loves their bottom-left origin
         0, height, width, height, width, 0, 0, 0,
         rpi->mTransformMatrix);
      vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
      vgLoadMatrix(rpi->mTransformMatrix);
   }
   vgSeti(VG_SCISSORING, VG_FALSE);
   vgClear(0, 0, rpi->mScreenWidth, rpi->mScreenHeight);
   vgSeti(VG_SCISSORING, VG_TRUE);

   vgImageSubData(rpi->mImage, frame, pitch, rpi->mTexType, 0, 0, width, height);
   vgDrawImage(rpi->mImage);

#ifdef HAVE_FREETYPE
   if (msg && rpi->mFontsOn)
      rpi_draw_message(rpi, msg);
#else
   (void)msg;
#endif

   eglSwapBuffers(rpi->mDisplay, rpi->mSurface);

   return true;
}
Пример #4
0
// makeimage makes an image from a raw raster of red, green, blue, alpha values
void makeimage(VGfloat x, VGfloat y, int w, int h, VGubyte * data) {
	unsigned int dstride = w * 4;
	VGImageFormat rgbaFormat = VG_sABGR_8888;
	VGImage img = vgCreateImage(rgbaFormat, w, h, VG_IMAGE_QUALITY_BETTER);
	vgImageSubData(img, (void *)data, dstride, rgbaFormat, 0, 0, w, h);
	vgSetPixels(x, y, img, 0, 0, w, h);
	vgDestroyImage(img);
}
Пример #5
0
int render(int width, int height)
{
	static DWORD startTick =0; 
	static DWORD frames = 0;
	VGImage image;
	char buf[256];

	if((startTick == 0)||(frames > 50))
	{
		if(frames > 50)
			frames = 0;
		startTick = GetTickCount();
		frames++;
	}
	else
	{
		sprintf(buf, "fps:%2.2f frames/sec \n", (float)(frames++)*1000/(GetTickCount() - startTick));
		OutputDebugString(buf);
	}

	if(pReadFile == NULL)
	{
		pReadFile = fopen("test.rgb","rb");
		if(pReadFile)
			fseek(pReadFile, 0 , SEEK_SET);
	}

	if(pReadFile && (feof(pReadFile)))
		fseek(pReadFile, 0 , SEEK_SET);

	if(pReadFile)
		fread(pBuff, sizeof(BYTE),SRC_WIDTH*SRC_HEIGHT*2,pReadFile);

	image = vgCreateImage( VG_sRGB_565, SRC_WIDTH, SRC_HEIGHT, VG_IMAGE_QUALITY_BETTER );
	if(image == NULL)
		return -1;
	vgImageSubData( image, pBuff, SRC_WIDTH*2, VG_sRGB_565, 0, 0, SRC_WIDTH, SRC_HEIGHT);

	vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
	vgLoadIdentity();
	vgScale((VGfloat)width/SRC_WIDTH, (VGfloat)height/SRC_HEIGHT);

	vgTranslate(SRC_WIDTH, SRC_HEIGHT);
	vgRotate(180.0f);
	vgDrawImage( image );

	vgDestroyImage( image );

    if ( vgGetError() == VG_NO_ERROR ) 
        eglSwapBuffers( egldisplay, eglsurface );

	return 0;
}
Пример #6
0
NativeImagePtr RGBA32Buffer::asNewNativeImage() const
{
    if (!m_image) {
        static const VGImageFormat bufferFormat = VG_sARGB_8888_PRE;

        // Save memory by using 16-bit images for fully opaque images.
        const VGImageFormat imageFormat = hasAlpha()
            ? WEBKIT_OPENVG_NATIVE_IMAGE_FORMAT_s_8888
            : VG_sRGB_565;

#if PLATFORM(EGL)
        EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent();
#endif

        const IntSize vgMaxImageSize(vgGeti(VG_MAX_IMAGE_WIDTH), vgGeti(VG_MAX_IMAGE_HEIGHT));
        ASSERT_VG_NO_ERROR();

        PassRefPtr<TiledImageOpenVG> tiledImage = adoptRef(new TiledImageOpenVG(
            IntSize(width(), height()), vgMaxImageSize));

        const int numColumns = tiledImage->numColumns();
        const int numRows = tiledImage->numRows();

        for (int yIndex = 0; yIndex < numRows; ++yIndex) {
            for (int xIndex = 0; xIndex < numColumns; ++xIndex) {
                IntRect tileRect = tiledImage->tileRect(xIndex, yIndex);
                VGImage tile = vgCreateImage(imageFormat,
                    tileRect.width(), tileRect.height(), VG_IMAGE_QUALITY_FASTER);
                ASSERT_VG_NO_ERROR();

                PixelData* pixelData = m_bytes.data();
                pixelData += (tileRect.y() * width()) + tileRect.x();

                vgImageSubData(tile, reinterpret_cast<unsigned char*>(pixelData),
                    width() * sizeof(PixelData), bufferFormat,
                    0, 0, tileRect.width(), tileRect.height());
                ASSERT_VG_NO_ERROR();

                tiledImage->setTile(xIndex, yIndex, tile);
            }
        }

        // Incomplete images will be returned without storing them in m_image,
        // so the image will be regenerated once loading is complete.
        if (m_status != FrameComplete)
            return tiledImage;

        m_image = tiledImage;
        m_bytes.clear();
    }

    return m_image; // and increase refcount
}
Пример #7
0
VGImage QVGPixmapData::toVGImage()
{
    if (!isValid() || failedToAlloc)
        return VG_INVALID_HANDLE;

#if !defined(QT_NO_EGL)
    // Increase the reference count on the shared context.
    if (!context)
        context = qt_vg_create_context(0, QInternal::Pixmap);
#endif

    if (recreate && prevSize != QSize(w, h))
        destroyImages();
    else if (recreate)
        cachedOpacity = -1.0f;  // Force opacity image to be refreshed later.

#if defined(Q_OS_SYMBIAN)
    if (recreate && nativeImageHandleProvider && !nativeImageHandle) {
        createFromNativeImageHandleProvider();
    }
#endif

    if (vgImage == VG_INVALID_HANDLE) {
        vgImage = QVGImagePool::instance()->createImageForPixmap
            (qt_vg_image_to_vg_format(source.format()), w, h, VG_IMAGE_QUALITY_FASTER, this);

        // Bail out if we run out of GPU memory - try again next time.
        if (vgImage == VG_INVALID_HANDLE) {
            failedToAlloc = true;
            return VG_INVALID_HANDLE;
        }

        inImagePool = true;
    } else if (inImagePool) {
        QVGImagePool::instance()->useImage(this);
    }

    if (!source.isNull() && recreate) {
        source.beginDataAccess();
        vgImageSubData
            (vgImage,
             source.constBits(), source.bytesPerLine(),
             qt_vg_image_to_vg_format(source.format()), 0, 0, w, h);
        source.endDataAccess(true);
    }

    recreate = false;
    prevSize = QSize(w, h);

    return vgImage;
}
Пример #8
0
static void rpi_render_message(rpi_t *rpi, const char *msg)
{
   free(rpi->mLastMsg);
   rpi->mLastMsg = strdup(msg);

   if (rpi->mMsgLength)
   {
      while (--rpi->mMsgLength)
         vgClearGlyph(rpi->mFont, rpi->mMsgLength);

      vgClearGlyph(rpi->mFont, 0);
   }

   struct font_output_list out;
   font_renderer_msg(rpi->mFontRenderer, msg, &out);
   struct font_output *head = out.head;

   while (head)
   {
      if (rpi->mMsgLength >= 1024)
         break;

      VGfloat origin[2], escapement[2];
      VGImage img;

      escapement[0] = head->advance_x;
      escapement[1] = head->advance_y;
      origin[0] = -head->char_off_x;
      origin[1] = -head->char_off_y;

      img = vgCreateImage(VG_A_8, head->width, head->height, VG_IMAGE_QUALITY_NONANTIALIASED);

      // flip it
      for (unsigned i = 0; i < head->height; i++)
         vgImageSubData(img, head->output + head->pitch * i, head->pitch, VG_A_8, 0, head->height - i - 1, head->width, 1);

      vgSetGlyphToImage(rpi->mFont, rpi->mMsgLength, img, origin, escapement);
      vgDestroyImage(img);

      rpi->mMsgLength++;
      head = head->next;
   }

   font_renderer_free_output(&out);

   for (unsigned i = 0; i < rpi->mMsgLength; i++)
      rpi->mGlyphIndices[i] = i;
}
Пример #9
0
static bool gfx_ctx_vc_image_buffer_write(void *data, const void *frame, unsigned width,
      unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
{
   bool ret = false;
   vc_ctx_data_t *vc = (vc_ctx_data_t*)data;

   if (!vc || index >= MAX_EGLIMAGE_TEXTURES)
      goto error;

   eglBindAPI(EGL_OPENVG_API);
   eglMakeCurrent(vc->egl.dpy, vc->pbuff_surf, vc->pbuff_surf, vc->eglimage_ctx);

   if (!vc->eglBuffer[index] || !vc->vgimage[index])
   {
      vc->vgimage[index] = vgCreateImage(
            rgb32 ? VG_sXRGB_8888 : VG_sRGB_565,
            vc->res,
            vc->res,
            VG_IMAGE_QUALITY_NONANTIALIASED);
      vc->eglBuffer[index] = peglCreateImageKHR(
            vc->egl.dpy,
            vc->eglimage_ctx,
            EGL_VG_PARENT_IMAGE_KHR,
            (EGLClientBuffer)vc->vgimage[index],
            NULL);
      ret = true;
   }

   vgImageSubData(
         vc->vgimage[index],
         frame, pitch,
         (rgb32 ? VG_sXRGB_8888 : VG_sRGB_565),
         0,
         0,
         width,
         height);
   *image_handle = vc->eglBuffer[index];

   gfx_ctx_vc_bind_api(NULL, vc_api, 0, 0);
   eglMakeCurrent(vc->egl.dpy, vc->egl.surf, vc->egl.surf, vc->egl.ctx);

   return ret;

error:
   *image_handle = NULL;
   return false;
}
Пример #10
0
VGImage createImageFromRaw(const char * filename) {
	FILE  *fp = fopen(filename, "rb");

	if (!fp) {
		printf("File %s not found.\n", filename);
    }

	VGubyte *sourceImage;
	long int imageSize;

	fseek(fp, 0L, SEEK_END);
    imageSize = ftell(fp);
    fseek(fp, 0L, SEEK_SET);

	sourceImage = (VGubyte *)malloc(imageSize-8);
	assert(sourceImage != NULL);

	int *dimensions;
	dimensions = (int*)malloc(8);
	long int nrDimensionElements = fread(dimensions, 4, 2, fp);
	assert(nrDimensionElements == 2);

	fseek(fp, 8L, SEEK_SET);

	long int nrbytes = fread(sourceImage, 1, imageSize-8, fp);
	assert(nrbytes == imageSize-8);

	int w = dimensions[0];
	int h = dimensions[1];

	printf("Reading raw image with dimensions %d x %d\n", w, h);

	unsigned int dstride = w * 4;
	VGImageFormat rgbaFormat = VG_sABGR_8888;

	VGImage img = vgCreateImage(rgbaFormat, w, h, VG_IMAGE_QUALITY_BETTER);
	vgImageSubData(img, (void *)sourceImage, dstride, rgbaFormat, 0, 0, w, h);
	

	fclose(fp);
	free(dimensions);
	free(sourceImage);

	return img;
}
Пример #11
0
VGImage QVGPixmapData::toVGImage()
{
    if (!isValid())
        return VG_INVALID_HANDLE;

#if !defined(QT_NO_EGL)
    // Increase the reference count on the shared context.
    if (!context)
        context = qt_vg_create_context(0, QInternal::Pixmap);
#endif

    if (recreate && prevSize != QSize(w, h))
        destroyImages();
    else if (recreate)
        cachedOpacity = -1.0f;  // Force opacity image to be refreshed later.

    if (vgImage == VG_INVALID_HANDLE) {
        vgImage = QVGImagePool::instance()->createImageForPixmap
            (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER, this);

        // Bail out if we run out of GPU memory - try again next time.
        if (vgImage == VG_INVALID_HANDLE)
            return VG_INVALID_HANDLE;

        inImagePool = true;
    } else if (inImagePool) {
        QVGImagePool::instance()->useImage(this);
    }

    if (!source.isNull() && recreate) {
        vgImageSubData
            (vgImage,
             source.constBits(), source.bytesPerLine(),
             VG_sARGB_8888_PRE, 0, 0, w, h);
    }

    recreate = false;
    prevSize = QSize(w, h);

    return vgImage;
}
Пример #12
0
NativeImagePtr RGBA32Buffer::asNewNativeImage() const
{
    static const VGImageFormat bufferFormat = VG_sARGB_8888_PRE;
    // Save memory by using 16-bit images for fully opaque images.
    const VGImageFormat imageFormat = hasAlpha() ? bufferFormat : VG_sRGB_565;

#if PLATFORM(EGL)
    EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent();
#endif

    const IntSize vgMaxImageSize(vgGeti(VG_MAX_IMAGE_WIDTH), vgGeti(VG_MAX_IMAGE_HEIGHT));
    ASSERT_VG_NO_ERROR();

    TiledImageOpenVG* tiledImage = new TiledImageOpenVG(IntSize(width(), height()), vgMaxImageSize);

    const int numColumns = tiledImage->numColumns();
    const int numRows = tiledImage->numRows();

    for (int yIndex = 0; yIndex < numRows; ++yIndex) {
        for (int xIndex = 0; xIndex < numColumns; ++xIndex) {
            IntRect tileRect = tiledImage->tileRect(xIndex, yIndex);
            VGImage image = vgCreateImage(imageFormat,
                tileRect.width(), tileRect.height(), VG_IMAGE_QUALITY_FASTER);
            ASSERT_VG_NO_ERROR();

            PixelData* pixelData = const_cast<PixelData*>(m_bytes);
            pixelData += (tileRect.y() * width()) + tileRect.x();

            vgImageSubData(image, reinterpret_cast<unsigned char*>(pixelData),
                width() * sizeof(PixelData), bufferFormat,
                0, 0, tileRect.width(), tileRect.height());
            ASSERT_VG_NO_ERROR();

            tiledImage->setTile(xIndex, yIndex, image);
        }
    }

    return tiledImage;
}
Пример #13
0
void ImageBufferData::transformColorSpace(const Vector<int>& lookUpTable)
{
    ASSERT(m_surface);

    VGint width = m_surface->width();
    VGint height = m_surface->height();

    VGubyte* data = new VGubyte[width * height * 4];
    VGubyte* currentPixel = data;

    if (!m_tiledImage)
        m_surface->makeCurrent();

    if (m_surface->isCurrent())
        vgReadPixels(data, width * 4, IMAGEBUFFER_VG_EXCHANGE_FORMAT, 0, 0, width, height);
    else
        vgGetImageSubData(m_tiledImage->tile(0, 0), data, width * 4, IMAGEBUFFER_VG_EXCHANGE_FORMAT, 0, 0, width, height);

    ASSERT_VG_NO_ERROR();

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; currentPixel += 4, x++) {
            currentPixel[IMAGEBUFFER_A] = lookUpTable[currentPixel[IMAGEBUFFER_A]];
            currentPixel[IMAGEBUFFER_R] = lookUpTable[currentPixel[IMAGEBUFFER_R]];
            currentPixel[IMAGEBUFFER_G] = lookUpTable[currentPixel[IMAGEBUFFER_G]];
            currentPixel[IMAGEBUFFER_B] = lookUpTable[currentPixel[IMAGEBUFFER_B]];
        }
    }

    if (m_surface->isCurrent())
        vgWritePixels(data, width * 4, IMAGEBUFFER_VG_EXCHANGE_FORMAT, 0, 0, width, height);
    else
        vgImageSubData(m_tiledImage->tile(0, 0), data, width * 4, IMAGEBUFFER_VG_EXCHANGE_FORMAT, 0, 0, width, height);

    ASSERT_VG_NO_ERROR();

    delete[] data;
}
Пример #14
0
int EGLUtilsVG::loadTexture(const char *fn)
{
    char testr[256];
    sprintf(testr, ":/%s", fn );
    QString filename = QString( testr );
    QImage image = QImage( filename );

    int w=image.width();
    int h=image.height();

    qDebug() << filename << "w:" << w << "h:" << h;

    VGImage texture = vgCreateImage(VG_sARGB_8888, w, h, VG_IMAGE_QUALITY_BETTER);
    qDebug("vgCreateImage handle %x", texture);
    if(texture==VG_INVALID_HANDLE)
    {
        VGErrorCode err = vgGetError();
        qDebug("loadVGImage '%s' error 0x%x", fn, err);
    }

    vgImageSubData(texture, (QRgb*)image.bits(), w*4, VG_sARGB_8888, 0, 0, w, h);
    return texture;
}
Пример #15
0
void ImageBufferData::putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, VGImageFormat format)
{
    ASSERT(m_surface);

    ASSERT(sourceRect.width() > 0);
    ASSERT(sourceRect.height() > 0);

    // We expect the sourceRect to be a subset of the given source image.
    ASSERT(sourceRect.x() >= 0);
    ASSERT(sourceRect.y() >= 0);
    ASSERT(sourceRect.right() <= source->width());
    ASSERT(sourceRect.bottom() <= source->height());

    // The target origin point is the combined offset of sourceRect.location()
    // and destPoint.
    int destx = destPoint.x() + sourceRect.x();
    int desty = destPoint.y() + sourceRect.y();
    ASSERT(destx >= 0);
    ASSERT(desty >= 0);
    ASSERT(destx + sourceRect.width() <= size.width());
    ASSERT(desty + sourceRect.height() <= size.height());

    unsigned const char* data = source->data()->data()->data();
    int dataOffset = (sourceRect.y() * source->width() * 4) + (sourceRect.x() * 4);

    if (!m_tiledImage)
        m_surface->makeCurrent();

    if (m_surface->isCurrent()) {
        vgWritePixels(data + dataOffset, source->width() * 4, format,
            destx, desty, sourceRect.width(), sourceRect.height());
    } else {
        vgImageSubData(m_tiledImage->tile(0, 0), data + dataOffset, source->width() * 4, format,
            destx, desty, sourceRect.width(), sourceRect.height());
    }
    ASSERT_VG_NO_ERROR();
}
Пример #16
0
void SubtitleRenderer::load_glyph(char32_t codepoint) {
  VGfloat escapement[2]{};

  auto load_glyph_internal =
  [&](FT_Face ft_face, VGFont vg_font, bool border) {
    try {
      auto glyph_index = FT_Get_Char_Index(ft_face, codepoint);
      ENFORCE(!FT_Load_Glyph(ft_face, glyph_index, FT_LOAD_NO_HINTING));

      FT_Glyph glyph;
      ENFORCE(!FT_Get_Glyph(ft_face->glyph, &glyph));
      SCOPE_EXIT {FT_Done_Glyph(glyph);};

      if (border)
        ENFORCE(!FT_Glyph_StrokeBorder(&glyph, ft_stroker_, 0, 1));

      ENFORCE(!FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, NULL, 1));
      FT_BitmapGlyph bit_glyph = (FT_BitmapGlyph) glyph;
      FT_Bitmap& bitmap = bit_glyph->bitmap;

      VGImage image{};
      VGfloat glyph_origin[2]{};

      if (bitmap.width > 0 && bitmap.rows > 0) {
        constexpr VGfloat blur_stddev = 0.6;
        const int padding = static_cast<int>(3*blur_stddev + 0.5);
        const int image_width = bitmap.width + padding*2;
        const int image_height = bitmap.rows + padding*2;

        image = vgCreateImage(VG_A_8, image_width, image_height,
                              VG_IMAGE_QUALITY_NONANTIALIASED);
        assert(image);
        
        if (bitmap.pitch > 0) {
          vgImageSubData(image,
                         bitmap.buffer + bitmap.pitch*(bitmap.rows-1),
                         -bitmap.pitch,
                         VG_A_8,
                         padding,
                         padding,
                         bitmap.width,
                         bitmap.rows);
          assert(!vgGetError());
        } else {
          vgImageSubData(image,
                         bitmap.buffer,
                         bitmap.pitch,
                         VG_A_8,
                         padding,
                         padding,
                         bitmap.width,
                         bitmap.rows);
          assert(!vgGetError());
        }

        auto softened_image = vgCreateImage(VG_A_8,
                                            image_width,
                                            image_height,
                                            VG_IMAGE_QUALITY_NONANTIALIASED);
        assert(image);

        // Even out hard and soft edges
        vgGaussianBlur(softened_image, image, blur_stddev, blur_stddev, VG_TILE_FILL);
        assert(!vgGetError());

        vgDestroyImage(image);
        assert(!vgGetError());

        image = softened_image;

        glyph_origin[0] = static_cast<VGfloat>(padding - bit_glyph->left);
        glyph_origin[1] = static_cast<VGfloat>(padding + bitmap.rows - bit_glyph->top - 1);
      }

      escapement[0] = static_cast<VGfloat>((ft_face->glyph->advance.x + 32) / 64);
      escapement[1] = 0;

      vgSetGlyphToImage(vg_font, codepoint, image, glyph_origin, escapement);
      assert(!vgGetError());

      if (image) {
        vgDestroyImage(image);
        assert(!vgGetError());
      }
    } catch(...) {
      escapement[0] = 0;
      escapement[1] = 0;
      vgSetGlyphToImage(vg_font, codepoint, VG_INVALID_HANDLE, escapement, escapement);
      assert(!vgGetError());
    }
  };

  load_glyph_internal(ft_face_, vg_font_, false);
  glyphs_[codepoint].advance = escapement[0];
  load_glyph_internal(ft_face_, vg_font_border_, true);
}
void CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doThreadFunctionL(TInt aIdx)
	{	
	INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doThreadFunctionL, Thread %d"),aIdx);
	CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
	eglSess->InitializeL();
	eglSess->OpenSgDriverL();

	INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
	TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
	TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize);
	// Create a pixmap surface matching the native image pixel format
	eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
	
	// Create a VGImage from the EGLImage
	INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the shared EGLImage"),aIdx);
	VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)iEGLImageShared);	
	ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
	
	Rendezvous(aIdx);
		
	if(aIdx == 0)
		{
		INFO_PRINTF2(_L("Thread %d, Updating contents of the VGImage from the shared EGLImage"),aIdx);
		TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
		CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 8);
    	// Add pixel data to the VGImage reference from the bitmap reference. 
        // Mind the fact that CFbsBitmap and VGImages use different coordinates origin!
		TSize bitmapSize = bitmap->SizeInPixels();
    	TUint8* address = reinterpret_cast<TUint8*>(bitmap->DataAddress());
    	TInt stride = bitmap->DataStride();
    	address += (bitmapSize.iHeight - 1) * stride;
        vgImageSubData(vgImageLocal, address, -stride, KDefaultSurfaceFormat, 0,0, bitmapSize.iWidth, bitmapSize.iHeight);
		delete bitmap;
        bitmap = NULL;
		ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
		eglWaitClient();
		}

	Rendezvous(aIdx);
	
	if(aIdx == 1)
		{
		INFO_PRINTF2(_L("Thread %d, Drawing the VGImage to the current surface"),aIdx);
		// Copy the source VGImage to the surface
    	vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight);
		ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
		eglWaitClient();

		// we can now compare the VgImage to the one we expect after changing it in the other thread
		TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
		CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 8);
		CleanupStack::PushL(refBitmap);
		eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
		CleanupStack::PopAndDestroy(refBitmap);
		INFO_PRINTF2(_L("Thread %d, Drawing successful"),aIdx);
		}		
	
	// cleanup
	vgDestroyImage(vgImageLocal);
	ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
	eglSess->CloseSgDriver();
	CleanupStack::PopAndDestroy(eglSess);
	}
Пример #18
0
/*******************************************************************************
 * Function Name  : InitView
 * Returns        : true if no error occured
 * Description    : Code in InitView() will be called by the Shell upon a change
 *					in the rendering context.
 *					Used to initialise variables that are dependent on the rendering
 *					context (e.g. textures, vertex buffers, etc.)
 *******************************************************************************/
bool CChildImage::InitView()
{
	//Create an image
	m_vgImage = vgCreateImage(VG_sRGBA_8888, IMG_SIZE, IMG_SIZE, VG_IMAGE_QUALITY_NONANTIALIASED);

	/*
	Populate the image from memory. A 32bit integer array (8bits per component)
	is created and populated.
	*/

	VGuint* pui32ImgData = new VGuint[IMG_SIZE*IMG_SIZE];

	for(int i = 0; i < IMG_SIZE; ++i)
	{
		for(int j = 0; j < IMG_SIZE; ++j)
		{
			// Fills the data with a fancy pattern
			if ( ((i*j)/8) % 2 )
				pui32ImgData[j*IMG_SIZE+i] = PVRTRGBA(255,255,0,255);
			else
				pui32ImgData[j*IMG_SIZE+i] = PVRTRGBA(255, 255 - (j * 2), 255 - i, 255 - (i * 2));
		}
	}

	/*
	The data in the array is then copied to the portion of the image starting at (0,0) through to (IMG_SIZE, IMG_SIZE), in
	this case that is the whole image. The coordinate system of the image places (0,0) at the bottom left-hand corner and
	(IMG_SIZE, IMG_SIZE) at the top right-hand corner.
	*/
	vgImageSubData(m_vgImage, pui32ImgData, sizeof(VGuint) * IMG_SIZE, VG_sRGBA_8888, 0, 0, IMG_SIZE, IMG_SIZE);

	// Delete the image data as it is now in OpenVG memory
	delete[] pui32ImgData;
	pui32ImgData = 0;

	//Create child images

	/*
	The first child is a child of m_vgImage and is made up of the region of m_vgImage from (0,0) to (IMG_SIZE / 2, IMG_SIZE / 2).
	Note: The area specified must be in the bounds of the parent.
	*/
	m_avgChildImages[0] = vgChildImage(m_vgImage,  0, 0, (VGint) (IMG_SIZE * 0.5), (VGint) (IMG_SIZE * 0.5));

	//The second child is a clone of the first child.

	//Get the dimensions of the first child..
	int i32ChildWidth = vgGetParameteri(m_avgChildImages[0], VG_IMAGE_WIDTH);
	int i32ChildHeight= vgGetParameteri(m_avgChildImages[0], VG_IMAGE_HEIGHT);

	//..and use them to define the region for creating the second child.
	m_avgChildImages[1] = vgChildImage(m_avgChildImages[0],  0, 0, i32ChildWidth,  i32ChildHeight);

	/*
	Clear a small portion of the bottom left-hand corner of m_avgChildImages[0] to red.
	This change will be seen in all relatives of m_avgChildImages[0], reason being they
	all share the same physical memory.

	Note:

	When clearing you specify the coordinate you want to start from and then how many pixels
	across and up you want to clear.
	*/
	VGfloat afClearColour[] = {1.0f, 0.0f, 0.0f, 1.0f};
	vgSetfv(VG_CLEAR_COLOR, 4, afClearColour);
	vgClearImage(m_avgChildImages[0], 0, 0, 10, 10);

	//Set the clear colour for clearing the sceen
	afClearColour[0] = 0.6f;
	afClearColour[1] = 0.8f;
	afClearColour[2] = 1.0f;
	afClearColour[3] = 1.0f;

	vgSetfv(VG_CLEAR_COLOR, 4, afClearColour);

	m_PrintVG.Initialize(PVRShellGet(prefWidth), PVRShellGet(prefHeight));
	return true;
}
Пример #19
0
/**
Overridden function, which creates Open VG images for foreground, background, shadow and outline components of the font.
 
@param 	aGlyphImage Source bitmap data in 256 grey format. Each pixel value is an index to a constant lookup table. 
			Four entries of this table represent % of Outline, Shadow, Fill and Background colour to be used to get the final colour to be displayed on screen.
@param	aGlyphImageSize Size of the glyph bitmap image.
@param	aForeground Foreground component of the glyph.
@param	aOutline	Outline component of the glyph.
@param	aShadow 	Shadow component of the glyph. 
@param	aPreAllocForeground Pre-allocated buffer which will be used for setting text foreground VG image
@param	aPreAllocOutline Pre-allocated buffer which will be used for setting text outline VG image
@param	aPreAllocShadow Pre-allocated buffer which will be used for setting text shadow VG image

@post 	Requested OpenVG images are ready for rendering. 
*/
void CFontGlyphTree::CreateVGImageL(const TUint8* aGlyphImage, const TSize& aGlyphImageSize, VGImage& aForeground, VGImage& aOutline, VGImage& aShadow, TUint8* aPreAllocForeground, TUint8* aPreAllocOutline, TUint8* aPreAllocShadow)
	{
	TInt dataStride = aGlyphImageSize.iWidth;
	TInt targetByteCount = dataStride * aGlyphImageSize.iHeight;
		// Allocate memory and transform source into target format.
		//
	TAny* foregroundBuffer = NULL;
	TAny* outlineBuffer = NULL;
	TAny* shadowBuffer = NULL;
	TBool destroyTempBuffer = EFalse;
	
	if(aPreAllocForeground && aPreAllocOutline && aPreAllocShadow && 
			(aGlyphImageSize.iWidth <= KMaxSizeImageOOM.iWidth) && 
			(aGlyphImageSize.iHeight <= KMaxSizeImageOOM.iHeight))
		{
		foregroundBuffer = aPreAllocForeground;
		outlineBuffer = aPreAllocOutline;
		shadowBuffer = aPreAllocShadow;
		}
	else
		{
		foregroundBuffer = User::AllocL(targetByteCount);
		CleanupStack::PushL(foregroundBuffer);
		outlineBuffer = User::AllocL(targetByteCount);
		CleanupStack::PushL(outlineBuffer);
		shadowBuffer = User::AllocL(targetByteCount);
		CleanupStack::PushL(shadowBuffer);
		destroyTempBuffer = ETrue;
		}	

	TUint8* foregroundByte = static_cast <TUint8*> (foregroundBuffer); 
	TUint8* outlineByte = static_cast <TUint8*> (outlineBuffer);
	TUint8* shadowByte = static_cast <TUint8*> (shadowBuffer);
				
	const TUint8* endByte = (TUint8*)aGlyphImage + targetByteCount;
	TUint8* curSrcGlyphImage = const_cast <TUint8*> (aGlyphImage);
	
	while (curSrcGlyphImage < endByte)
		{
		*outlineByte++ = FourColorBlendLookup[*curSrcGlyphImage] [KOutlineColorIndex];
		*shadowByte++ = FourColorBlendLookup[*curSrcGlyphImage] [KShadowColorIndex];
		*foregroundByte++ = FourColorBlendLookup[*curSrcGlyphImage] [KFillColorIndex];
		curSrcGlyphImage++;
		}

	const VGImageFormat imageFormat = VG_sL_8;
	if(aForeground == VG_INVALID_HANDLE)
		{
		aForeground = vgCreateImage(imageFormat,
	                              aGlyphImageSize.iWidth, 
	                              aGlyphImageSize.iHeight,
	                              VG_IMAGE_QUALITY_NONANTIALIASED);
		if(aForeground == VG_INVALID_HANDLE)
			{
			User::Leave(KErrNoMemory);
			}
		aOutline = vgCreateImage(imageFormat,
	                              aGlyphImageSize.iWidth, 
	                              aGlyphImageSize.iHeight,
	                              VG_IMAGE_QUALITY_NONANTIALIASED);
		if(aOutline == VG_INVALID_HANDLE)
			{
			DestroyVGImage(&aForeground);
			User::Leave(KErrNoMemory);
			}

		aShadow = vgCreateImage(imageFormat,
	                              aGlyphImageSize.iWidth, 
	                              aGlyphImageSize.iHeight,
	                              VG_IMAGE_QUALITY_NONANTIALIASED);
		if(aShadow == VG_INVALID_HANDLE)
			{
			DestroyVGImage(&aForeground, &aOutline);
			User::Leave(KErrNoMemory);	
			}
		}
	
	vgImageSubData(
		aForeground, foregroundBuffer, 
		dataStride,	imageFormat, 
		0, 0,aGlyphImageSize.iWidth, aGlyphImageSize.iHeight);
	
#ifdef DRAWGLYPH_MULTIPLY_MODE
		VGImage image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);		
		vgColorMatrix(image, aForeground, KColorMatrix);
		vgDestroyImage(aForeground);
		aForeground = image;
#endif // DRAWGLYPH_MULTIPLY_MODE
		
	vgImageSubData(
		aOutline, outlineBuffer, 
		dataStride,	imageFormat, 
		0, 0, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight);
	
#ifdef DRAWGLYPH_MULTIPLY_MODE
		image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);		
		vgColorMatrix(image, aOutline, KColorMatrix);
		vgDestroyImage(aOutline);
		aOutline = image;
#endif // DRAWGLYPH_MULTIPLY_MODE
		
	vgImageSubData(
		aShadow, shadowBuffer, 
		dataStride,	imageFormat, 
		0, 0, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight);
	
#ifdef DRAWGLYPH_MULTIPLY_MODE
		image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);		
		vgColorMatrix(image, aShadow, KColorMatrix);
		vgDestroyImage(aShadow);
		aShadow = image;
#endif // DRAWGLYPH_MULTIPLY_MODE	
	
	if(destroyTempBuffer)
		{
		CleanupStack::PopAndDestroy(3, foregroundBuffer);
		}
	}
Пример #20
0
/**
Overridden function, which creates OpenVG images for monochrome and anti-aliased fonts.
 
@param 	aGlyphImage Data source bitmap in 256 or 2 Grey format. 
@param 	aGlyphImageSize Glyph image data size.
@param 	aDisplayMode Image display mode.
@param	aForeground Foreground component of the glyph.
@param	aPreAllocForeground Pre-allocated buffer which will be used for setting foreground VG image

@post 	Requested OpenVG image is ready for rendering. 

@panic 	Panic if bitmap display mode is not 256 grey or 2 grey.
*/
void CFontGlyphTree::CreateVGImageL(const TUint8* aGlyphImage, const TSize& aGlyphImageSize, TDisplayMode aDisplayMode, VGImage& aForeground, TUint8* aPreAllocForeground)
	{
	GRAPHICS_ASSERT_DEBUG((aDisplayMode == EGray256) || (aDisplayMode == EGray2), EDirectGdiPanicInvalidDisplayMode);
	GRAPHICS_ASSERT_DEBUG(aGlyphImage, EDirectGdiPanicInvalidParameter);
	
	VGImageFormat imageFormat = VG_IMAGE_FORMAT_INVALID;
	TInt  vgCompatibleSourceStride = 0x00;
	TUint32 binaryDataArray[32];
	TUint8* binaryData = NULL;
	TUint8* tempBuffer = NULL;	
	
	if(aDisplayMode == EGray256)
		{
		imageFormat = VG_sL_8;
		vgCompatibleSourceStride = aGlyphImageSize.iWidth; 
		binaryData = const_cast <TUint8*> (aGlyphImage);
		}
	else //EGray2
		{
		imageFormat = VG_BW_1;
		vgCompatibleSourceStride = ((aGlyphImageSize.iWidth + 31) / 32) << 2;
		if (aGlyphImageSize.iWidth > 30 || aGlyphImageSize.iHeight > 32)
			{
			binaryData = aPreAllocForeground;
			if(!binaryData)
				{
				tempBuffer = (TUint8*) User::AllocL(vgCompatibleSourceStride * aGlyphImageSize.iHeight);
				CleanupStack::PushL(tempBuffer);
				binaryData = tempBuffer;
				}
			DecodeBinaryDataExLarge(aGlyphImageSize, aGlyphImage, vgCompatibleSourceStride, reinterpret_cast <TUint32*> (binaryData));
			}
		else
			{
			DecodeBinaryData(aGlyphImageSize, aGlyphImage, binaryDataArray);
			binaryData = reinterpret_cast <TUint8*> (binaryDataArray);		
			}
		}

	if(aForeground == VG_INVALID_HANDLE)
		{
		aForeground = vgCreateImage(imageFormat,
                              aGlyphImageSize.iWidth, 
                              aGlyphImageSize.iHeight,
                              VG_IMAGE_QUALITY_NONANTIALIASED);
		}
	
	if (aForeground != VG_INVALID_HANDLE)
		{
			// Copy from the source image to our new VGImage
		vgImageSubData(aForeground, binaryData, vgCompatibleSourceStride,	imageFormat, 
			0,	0, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight);
		
#ifdef DRAWGLYPH_MULTIPLY_MODE
		VGImage image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);		
		vgColorMatrix(image, aForeground, KColorMatrix);
		vgDestroyImage(aForeground);
		aForeground = image;
#endif
		}
	else
		{
		if(tempBuffer)
			{
			CleanupStack::PopAndDestroy(tempBuffer);	
			}
		User::Leave(KErrNoMemory);
		}
		
	if(tempBuffer)
		{
		CleanupStack::PopAndDestroy(tempBuffer);	
		}
	}
Пример #21
0
/*******************************************************************************
 * Function Name  : InitView
 * Returns        : true if no error occured
 * Description    : Code in InitView() will be called by the Shell upon a change
 *					in the rendering context.
 *					Used to initialise variables that are dependent on the rendering
 *					context (e.g. textures, vertex buffers, etc.)
 *******************************************************************************/
bool CImage::InitView()
{
	//Create a pair of images
	m_avgImage[0] = vgCreateImage(VG_sRGBA_8888, IMG_SIZE, IMG_SIZE, VG_IMAGE_QUALITY_NONANTIALIASED);
	m_avgImage[1] = vgCreateImage(VG_sRGBA_8888, IMG_SIZE, IMG_SIZE, VG_IMAGE_QUALITY_NONANTIALIASED);

	/*
	The first image will be populated from memory. A 32bit integer array (8bits per component)
	is created and populated.
	*/

	VGuint* pui32ImgData = new VGuint[IMG_SIZE * IMG_SIZE];

	for (int i = 0; i < IMG_SIZE; ++i)
	{
		for (int j = 0; j < IMG_SIZE; ++j)
		{
			// Fills the data with a fancy pattern
			if ( ((i*j)/8) % 2 )
				pui32ImgData[j*IMG_SIZE+i] = PVRTRGBA(255,255,0,255);
			else
				pui32ImgData[j*IMG_SIZE+i] = PVRTRGBA(255, 255 - (j * 2), 255 - i, 255 - (i * 2));
		}
	}

	/*
	The data in the array is then copied to the portion of the image starting at (0,0) through to (IMG_SIZE, IMG_SIZE), in
	this case that is the whole image. The coordinate system of the image places (0,0) at the bottom left-hand corner and
	(IMG_SIZE, IMG_SIZE) at the top right-hand corner.
	*/
	vgImageSubData(m_avgImage[0],pui32ImgData, sizeof(VGuint) * IMG_SIZE,VG_sRGBA_8888, 0, 0, IMG_SIZE, IMG_SIZE);

	// Delete the image data as it is now in OpenVG memory
	delete[] pui32ImgData;
	pui32ImgData = 0;

	/*
	The second image will initially be cleared to a single colour and then a part of the first image
	will be copied to it.
	*/

	//The colour to clear the image to is taken from the currently set VG_CLEAR_COLOR.
	VGfloat afClearColour[] = { 1.0f, 0.8f, 0.6f, 1.0f };
	vgSetfv(VG_CLEAR_COLOR, 4, afClearColour);

	//Clear the part of the image in the range (0,0) to (IMG_SIZE, IMG_SIZE), in this case that is the whole image.
	vgClearImage(m_avgImage[1], 0, 0, IMG_SIZE, IMG_SIZE);

	/*
	Copy the bottom left-hand corner ((0,0) to (IMG_SIZE / 2, IMG_SIZE / 2)) of the first image
	into the the second image starting at (IMG_SIZE / 4, IMG_SIZE / 4).
	*/
	int i32ImgSizeQuarter = (int) (IMG_SIZE * 0.25);

	vgCopyImage(m_avgImage[1], i32ImgSizeQuarter, i32ImgSizeQuarter,
				m_avgImage[0], 0,0,
				(VGint) (IMG_SIZE * 0.5), (VGint) (IMG_SIZE * 0.5),
				(VGboolean) false);

	//Set the clear colour for clearing the sceen
	afClearColour[0] = 0.6f;
	afClearColour[1] = 0.8f;
	afClearColour[2] = 1.0f;
	afClearColour[3] = 1.0f;

	vgSetfv(VG_CLEAR_COLOR, 4, afClearColour);

	m_PrintVG.Initialize(PVRShellGet(prefWidth), PVRShellGet(prefHeight));
	return true;
}
Пример #22
0
// createImageFromJpeg decompresses a JPEG image to the standard image format
// source: https://github.com/ileben/ShivaVG/blob/master/examples/test_image.c
VGImage createImageFromJpeg(const char *filename) {
	FILE *infile;
	struct jpeg_decompress_struct jdc;
	struct jpeg_error_mgr jerr;
	JSAMPARRAY buffer;
	unsigned int bstride;
	unsigned int bbpp;

	VGImage img;
	VGubyte *data;
	unsigned int width;
	unsigned int height;
	unsigned int dstride;
	unsigned int dbpp;

	VGubyte *brow;
	VGubyte *drow;
	unsigned int x;
	unsigned int lilEndianTest = 1;
	VGImageFormat rgbaFormat;

	// Check for endianness
	if (((unsigned char *)&lilEndianTest)[0] == 1)
		rgbaFormat = VG_sABGR_8888;
	else
		rgbaFormat = VG_sRGBA_8888;

	// Try to open image file
	infile = fopen(filename, "rb");
	if (infile == NULL) {
		printf("Failed opening '%s' for reading!\n", filename);
		return VG_INVALID_HANDLE;
	}
	// Setup default error handling
	jdc.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&jdc);

	// Set input file
	jpeg_stdio_src(&jdc, infile);

	// Read header and start
	jpeg_read_header(&jdc, TRUE);
	jpeg_start_decompress(&jdc);
	width = jdc.output_width;
	height = jdc.output_height;

	// Allocate buffer using jpeg allocator
	bbpp = jdc.output_components;
	bstride = width * bbpp;
	buffer = (*jdc.mem->alloc_sarray)
	    ((j_common_ptr) & jdc, JPOOL_IMAGE, bstride, 1);

	// Allocate image data buffer
	dbpp = 4;
	dstride = width * dbpp;
	data = (VGubyte *) malloc(dstride * height);

	// Iterate until all scanlines processed
	while (jdc.output_scanline < height) {

		// Read scanline into buffer
		jpeg_read_scanlines(&jdc, buffer, 1);
		drow = data + (height - jdc.output_scanline) * dstride;
		brow = buffer[0];
		// Expand to RGBA
		for (x = 0; x < width; ++x, drow += dbpp, brow += bbpp) {
			switch (bbpp) {
			case 4:
				drow[0] = brow[0];
				drow[1] = brow[1];
				drow[2] = brow[2];
				drow[3] = brow[3];
				break;
			case 3:
				drow[0] = brow[0];
				drow[1] = brow[1];
				drow[2] = brow[2];
				drow[3] = 255;
				break;
			}
		}
	}

	// Create VG image
	img = vgCreateImage(rgbaFormat, width, height, VG_IMAGE_QUALITY_BETTER);
	vgImageSubData(img, data, dstride, rgbaFormat, 0, 0, width, height);

	// Cleanup
	jpeg_destroy_decompress(&jdc);
	fclose(infile);
	free(data);

	return img;
}
void CTReadWriteChild::WriteImageFuncL()
    {
    vgImageSubData(iImage, iData, iWidth*iByteSize, iFormat, 0, 0, iWidth, iHeight);
    VgLeaveIfErrorL();
    }
Пример #24
0
int createFont(FT_Face fontFace, FT_UInt size)
{
	initFreeTypeLibrary();

	VGfloat glyphOrigin[2];
	VGfloat escapement[2];

	FT_Stroker fontStroker;
	int error = FT_Stroker_New(freeTypeLibrary, &fontStroker);
	if (error) {
		logInfo(LOG_FREETYPE, "Error FT_Stroker_New.(error=%d)\n", error);
		return -1;
	}

	FT_Stroker_Set(fontStroker,
		 2*64.0f,  // Need to get the right value based on size.
		 FT_STROKER_LINECAP_ROUND,
		 FT_STROKER_LINEJOIN_ROUND,
		 0);

	VGFont tmpFont;
	struct fontListItem *tmpFontListItem = fontExists(fontFace, size);
	if (tmpFontListItem == NULL) {
		tmpFont = vgCreateFont(fontFace->num_glyphs);
		if (tmpFont == VG_INVALID_HANDLE) {
			logInfo(LOG_FREETYPE, "Error could not create vgCreateFont.\n");
			return -1;
		}

		tmpFontListItem = malloc(sizeof(struct fontListItem));
		tmpFontListItem->fontFace = fontFace;
		tmpFontListItem->size = size;
		tmpFontListItem->font = tmpFont;
		addToFontList(tmpFontListItem);
	}
	else {
		return 0;
	}

	error = FT_Set_Char_Size( fontFace, /* handle to face object */
					0, /* char_width in 1/64th of points */
					size*64, /* char_height in 1/64th of points */
					72, /* horizontal device resolution */
					72 ); /* vertical device resolution */

	if (error) {
		logInfo(LOG_FREETYPE, "Error FT_Set_Char_Size.(error=%d)\n", error);
		return -1;
	}

	int index;
	int counter = 0;
	FT_UInt charIndex;
	VGImage image = VG_INVALID_HANDLE;
	VGImage softenedImage;
	VGfloat blustStdDev;
	int padding;
	int image_width;
	int image_height;
	VGErrorCode vg_error;
	FT_Glyph glyph;

	logInfo(LOG_FREETYPE, "This font contains %ld glyphs.\n", fontFace->num_glyphs);

	for (index = 32; (index < 256) && (counter < fontFace->num_glyphs); index++) {
		counter++;
		charIndex = FT_Get_Char_Index(fontFace, index);

		logInfo(LOG_FREETYPE, "index=0x%x, charIndex=0x%x\n", index, charIndex);

		escapement[0] = 0;
		escapement[1] = 0;

		if (charIndex == 0) {
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			logInfo(LOG_FREETYPE, "charindex== 0\n");
			continue;
		}

		error = FT_Load_Glyph(fontFace, charIndex, FT_LOAD_NO_HINTING);
		if (error) {
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			logInfo(LOG_FREETYPE, "Error FT_Load_Glyph (error:%d)\n", error);
			continue;
		}

		error = FT_Get_Glyph(fontFace->glyph, &glyph);
		if (error) {
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			logInfo(LOG_FREETYPE, "Error FT_Get_Glyph (error:%d)\n", error);
			continue;
		}

/*
		error = FT_Glyph_StrokeBorder(&glyph, fontStroker, 0, 1);
		if (error) {
			FT_Done_Glyph(glyph);
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			logInfo(LOG_FREETYPE, "Error FT_Glyph_StrokeBorder (error:%d)\n", error);
			continue;
		}
*/

		error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, NULL, 1);
		if (error) {
			FT_Done_Glyph(glyph);
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			logInfo(LOG_FREETYPE, "Error FT_Glyph_To_Bitmap (error:%d)\n", error);
			continue;
		}

		FT_BitmapGlyph bitGlyph = (FT_BitmapGlyph)glyph;
		FT_Bitmap bitmap = bitGlyph->bitmap;

		if (bitmap.width > 0 && bitmap.rows > 0) {
			blustStdDev = 0.6;
			padding = (3*blustStdDev + 0.5);
			image_width = bitmap.width + padding*2;
			image_height = bitmap.rows + padding*2;

			image = vgCreateImage(VG_A_8, image_width, image_height, VG_IMAGE_QUALITY_NONANTIALIASED);
			if (image == VG_INVALID_HANDLE) {
				FT_Done_Glyph(glyph);
				vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
				logInfo(LOG_FREETYPE, "vgCreateImage (error:%d)\n", vgGetError());
				continue;
			}

			if (bitmap.pitch > 0) {
				vgImageSubData(image,
					 bitmap.buffer + bitmap.pitch*(bitmap.rows-1),
					 -bitmap.pitch,
					 VG_A_8,
					 padding,
					 padding,
					 bitmap.width,
					 bitmap.rows);
			} else {
				vgImageSubData(image,
					 bitmap.buffer,
					 bitmap.pitch,
					 VG_A_8,
					 padding,
					 padding,
					 bitmap.width,
					 bitmap.rows);
			}
			vg_error = vgGetError();
			if (vg_error) {
				vgDestroyImage(image);
				FT_Done_Glyph(glyph);
				vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
				showVGErrorStr(vg_error, "vgImageSubData");
				continue;
			}

			softenedImage = vgCreateImage(VG_A_8,
							image_width,
							image_height,
							VG_IMAGE_QUALITY_NONANTIALIASED);
			if (softenedImage == VG_INVALID_HANDLE) {
				vgDestroyImage(image);
				FT_Done_Glyph(glyph);
				vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
				logInfo(LOG_FREETYPE, "vgCreateImage (error:%d)\n", vgGetError());
				continue;
			}

			// Even out hard and soft edges
			vgGaussianBlur(softenedImage, image, blustStdDev, blustStdDev, VG_TILE_FILL);
			vg_error = vgGetError();
			if (vg_error) {
				vgDestroyImage(softenedImage);
				vgDestroyImage(image);
				FT_Done_Glyph(glyph);
				vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
				showVGErrorStr(vg_error, "vgGaussianBlur");
				continue;
			}

			vgDestroyImage(image);
			image = softenedImage;

			glyphOrigin[0] = (VGfloat)(padding - bitGlyph->left);
			glyphOrigin[1] = (VGfloat)(padding + bitmap.rows - bitGlyph->top - 1);

		}
		else {
			logInfo(LOG_FREETYPE, "Error bitmap.width = %d, bitmap.rows = %d\n", bitmap.width, bitmap.rows);
		}

		escapement[0] = (VGfloat)((fontFace->glyph->advance.x + 32) / 64);
		escapement[1] = 0;

		vgSetGlyphToImage(tmpFont, index, image, glyphOrigin, escapement);
		vg_error = vgGetError();
		if (vg_error) {
			vgDestroyImage(softenedImage);
			vgDestroyImage(image);
			FT_Done_Glyph(glyph);
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			showVGErrorStr(vg_error, "vgSetGlyphToImage");
			continue;
		}
		logInfo(LOG_FREETYPE, "Create glyph %d.\n", index);

		FT_Done_Glyph(glyph);

		if (image != VG_INVALID_HANDLE) {
			vgDestroyImage(image);
		}
	}

	return 0;
}