void QVGPixmapDropShadowFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const
{
    if (src.isNull())
        return;

    if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) {
        // The pixmap data is not an instance of QVGPixmapData, so fall
        // back to the default drop shadow filter implementation.
        QPixmapDropShadowFilter::draw(painter, dest, src, srcRect);
        return;
    }

    QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData());

    VGImage srcImage = pd->toVGImage();
    if (srcImage == VG_INVALID_HANDLE)
        return;

    QSize size = pd->size();
    VGImage dstImage = QVGImagePool::instance()->createTemporaryImage
        (VG_A_8, size.width(), size.height(),
         VG_IMAGE_QUALITY_FASTER, pd);
    if (dstImage == VG_INVALID_HANDLE)
        return;

    // Clamp the radius range.  We divide by 2 because the OpenVG blur
    // is "too blurry" compared to the default raster implementation.
    VGfloat maxRadius = VGfloat(vgGeti(VG_MAX_GAUSSIAN_STD_DEVIATION));
    VGfloat radiusF = VGfloat(blurRadius()) / 2.0f;
    if (radiusF < 0.001f)
        radiusF = 0.001f;
    else if (radiusF > maxRadius)
        radiusF = maxRadius;

    // Blur the blackened source image.
    vgGaussianBlur(dstImage, srcImage, radiusF, radiusF, VG_TILE_PAD);

    VGImage child = VG_INVALID_HANDLE;

    QRect srect;
    if (srcRect.isNull() ||
        (srcRect.topLeft().isNull() && srcRect.size() == size)) {
        child = dstImage;
        srect = QRect(0, 0, size.width(), size.height());
    } else {
        srect = srcRect.toRect();
        child = vgChildImage(dstImage, srect.x(), srect.y(), srect.width(), srect.height());
    }

    qt_vg_drawVGImageStencil(painter, dest + offset(), child, color());

    if(child != dstImage)
        vgDestroyImage(child);
    QVGImagePool::instance()->releaseImage(0, dstImage);

    // Now draw the actual pixmap over the top.
    painter->drawPixmap(dest, src, srect);
}
void QVGPixmapBlurFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const
{
    if (src.isNull())
        return;

    if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) {
        // The pixmap data is not an instance of QVGPixmapData, so fall
        // back to the default blur filter implementation.
        QPixmapBlurFilter::draw(painter, dest, src, srcRect);
        return;
    }

    QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData());

    VGImage srcImage = pd->toVGImage();
    if (srcImage == VG_INVALID_HANDLE)
        return;

    QSize size = pd->size();
    VGImage dstImage = QVGImagePool::instance()->createTemporaryImage
        (VG_sARGB_8888_PRE, size.width(), size.height(),
         VG_IMAGE_QUALITY_FASTER, pd);
    if (dstImage == VG_INVALID_HANDLE)
        return;

    // Clamp the radius range.  We divide by 2 because the OpenVG blur
    // is "too blurry" compared to the default raster implementation.
    VGfloat maxRadius = VGfloat(vgGeti(VG_MAX_GAUSSIAN_STD_DEVIATION));
    VGfloat radiusF = VGfloat(radius()) / 2.0f;
    if (radiusF < 0.001f)
        radiusF = 0.001f;
    else if (radiusF > maxRadius)
        radiusF = maxRadius;

    vgGaussianBlur(dstImage, srcImage, radiusF, radiusF, VG_TILE_PAD);

    VGImage child = VG_INVALID_HANDLE;

    if (srcRect.isNull() ||
        (srcRect.topLeft().isNull() && srcRect.size() == size)) {
        child = dstImage;
    } else {
        QRect src = srcRect.toRect();
        child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height());
    }

    qt_vg_drawVGImage(painter, dest, child);

    if(child != dstImage)
        vgDestroyImage(child);
    QVGImagePool::instance()->releaseImage(0, dstImage);
}
void CHuiFxVg10BlurFilter::DrawEffect(CHuiFxEngine& aEngine, VGImage aTargetImage, VGImage aSourceImage, TInt aWidth, TInt aHeight, TBool /*aHasSurface*/)
    {
    const VGfloat blur_x = clamp(iBlurX, EPSILON, 128.0f);
    const VGfloat blur_y = clamp(iBlurY, EPSILON, 128.0f);
    const VGfloat opacity = clamp(iOpacity, 0.0f, 1.0f);
    
    if(opacity < 1.0f - EPSILON)    // slow path --- take opacity into account
        {
//        const VGint width = vgGetParameteri(aSourceImage, VG_IMAGE_WIDTH);
//        const VGint height = vgGetParameteri(aSourceImage, VG_IMAGE_HEIGHT);
        const VGint width = aWidth;
        const VGint height = aHeight;
    
        CHuiFxRenderbuffer* auxBuffer = aEngine.AcquireRenderbuffer(TSize(width, height));
        if (!auxBuffer)
            {
            return;  // not enough memory --- filter not completed successfully
            }
        auxBuffer->BindAsTexture(ERenderbufferUsageReadWrite);
        
        VGImage auxImage = reinterpret_cast<CHuiFxVg10RenderbufferBase*>(auxBuffer)->Image();
        
        vgGaussianBlur(auxImage, aSourceImage, blur_x, blur_y, VG_TILE_PAD);
    
        if(OpacityChanged())
            {
            UpdateAlphaLUT();
            }
        vgLookup(aTargetImage, auxImage, iColorLUT, iColorLUT, iColorLUT, iAlphaLUT, VG_TRUE, VG_FALSE);
        auxBuffer->UnbindAsTexture();
        aEngine.ReleaseRenderbuffer(auxBuffer);
    }    
    else    // fast path --- the blur, just blur and nothing but the blur.
        {
        vgGaussianBlur(aTargetImage, aSourceImage, blur_x, blur_y, VG_TILE_PAD);   
        }
    }
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);
}
Beispiel #5
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;
}