예제 #1
0
TemporaryRef<DrawTarget>
Factory::CreateDrawTargetForData(BackendType aBackend, 
                                 unsigned char *aData, 
                                 const IntSize &aSize, 
                                 int32_t aStride, 
                                 SurfaceFormat aFormat)
{
  switch (aBackend) {
#ifdef USE_SKIA
  case BACKEND_SKIA:
    {
      RefPtr<DrawTargetSkia> newTarget;
      newTarget = new DrawTargetSkia();
      newTarget->Init(aData, aSize, aStride, aFormat);
      return newTarget;
    }
#endif
  default:
    gfxDebug() << "Invalid draw target type specified.";
    return NULL;
  }

  gfxDebug() << "Failed to create DrawTarget, Type: " << aBackend << " Size: " << aSize;
  // Failed
  return NULL;
}
예제 #2
0
MemoryTextureData*
MemoryTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                          gfx::BackendType aMoz2DBackend, TextureFlags aFlags,
                          TextureAllocationFlags aAllocFlags,
                          ClientIPCAllocator* aAllocator)
{
  // Should have used CreateForYCbCr.
  MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV);

  if (aSize.width <= 0 || aSize.height <= 0) {
    gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height;
    return nullptr;
  }

  uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat);
  if (!bufSize) {
    return nullptr;
  }

  uint8_t* buf = new (fallible) uint8_t[bufSize];
  if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags)) {
    return nullptr;
  }

  auto fwd = aAllocator ? aAllocator->AsCompositableForwarder() : nullptr;
  bool hasIntermediateBuffer = fwd ? ComputeHasIntermediateBuffer(aFormat,
                                              fwd->GetCompositorBackendType())
                                   : true;

  GfxMemoryImageReporter::DidAlloc(buf);

  BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasIntermediateBuffer);

  return new MemoryTextureData(descriptor, aMoz2DBackend, buf, bufSize);
}
예제 #3
0
already_AddRefed<DataSourceSurface>
SourceSurfaceD2DTarget::GetDataSurface()
{
  RefPtr<DataSourceSurfaceD2DTarget> dataSurf =
    new DataSourceSurfaceD2DTarget(mFormat);

  D3D10_TEXTURE2D_DESC desc;
  mTexture->GetDesc(&desc);

  desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
  desc.Usage = D3D10_USAGE_STAGING;
  desc.BindFlags = 0;
  desc.MiscFlags = 0;

  if (!Factory::GetDirect3D10Device()) {
    gfxCriticalError() << "Invalid D3D10 device in D2D target surface";
    return nullptr;
  }

  HRESULT hr = Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, byRef(dataSurf->mTexture));

  if (FAILED(hr)) {
    gfxDebug() << "Failed to create staging texture for SourceSurface. Code: " << hexa(hr);
    return nullptr;
  }
  Factory::GetDirect3D10Device()->CopyResource(dataSurf->mTexture, mTexture);

  return dataSurf.forget();
}
예제 #4
0
void
DrawTargetD2D1::PushClip(const Path *aPath)
{
  if (aPath->GetBackendType() != BackendType::DIRECT2D) {
    gfxDebug() << *this << ": Ignoring clipping call for incompatible path.";
    return;
  }

  RefPtr<PathD2D> pathD2D = static_cast<PathD2D*>(const_cast<Path*>(aPath));

  PushedClip clip;
  clip.mTransform = D2DMatrix(mTransform);
  clip.mPath = pathD2D;
  
  pathD2D->mGeometry->GetBounds(clip.mTransform, &clip.mBounds);

  mPushedClips.push_back(clip);

  // The transform of clips is relative to the world matrix, since we use the total
  // transform for the clips, make the world matrix identity.
  mDC->SetTransform(D2D1::IdentityMatrix());
  mTransformDirty = true;

  if (mClipsArePushed) {
    PushD2DLayer(mDC, pathD2D->mGeometry, clip.mTransform);
  }
}
예제 #5
0
MemoryTextureData*
MemoryTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                          gfx::BackendType aMoz2DBackend,
                          LayersBackend aLayersBackend, TextureFlags aFlags,
                          TextureAllocationFlags aAllocFlags,
                          LayersIPCChannel* aAllocator)
{
  // Should have used CreateForYCbCr.
  MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV);

  if (aSize.width <= 0 || aSize.height <= 0) {
    gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height;
    return nullptr;
  }

  uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat);
  if (!bufSize) {
    return nullptr;
  }

  uint8_t* buf = new (fallible) uint8_t[bufSize];
  if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags, false)) {
    return nullptr;
  }

  bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(aFormat, aLayersBackend);

  GfxMemoryImageReporter::DidAlloc(buf);

  BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasIntermediateBuffer);

  return new MemoryTextureData(descriptor, aMoz2DBackend, buf, bufSize);
}
예제 #6
0
static bool
InitBuffer(uint8_t* buf, size_t bufSize,
           gfx::SurfaceFormat aFormat, TextureAllocationFlags aAllocFlags,
           bool aAlreadyZero)
{
  if (!buf) {
    gfxDebug() << "BufferTextureData: Failed to allocate " << bufSize << " bytes";
    return false;
  }

  if ((aAllocFlags & ALLOC_CLEAR_BUFFER) ||
      (aAllocFlags & ALLOC_CLEAR_BUFFER_BLACK)) {
    if (aFormat == gfx::SurfaceFormat::B8G8R8X8) {
      // Even though BGRX was requested, XRGB_UINT32 is what is meant,
      // so use 0xFF000000 to put alpha in the right place.
      libyuv::ARGBRect(buf, bufSize, 0, 0, bufSize / sizeof(uint32_t), 1, 0xFF000000);
    } else if (!aAlreadyZero) {
      memset(buf, 0, bufSize);
    }
  }

  if (aAllocFlags & ALLOC_CLEAR_BUFFER_WHITE) {
    memset(buf, 0xFF, bufSize);
  }

  return true;
}
bool
SourceSurfaceD2D::InitFromData(unsigned char *aData,
                               const IntSize &aSize,
                               int32_t aStride,
                               SurfaceFormat aFormat,
                               ID2D1RenderTarget *aRT)
{
  HRESULT hr;

  mFormat = aFormat;
  mSize = aSize;

  if ((uint32_t)aSize.width > aRT->GetMaximumBitmapSize() ||
      (uint32_t)aSize.height > aRT->GetMaximumBitmapSize()) {
    gfxDebug() << "Bitmap does not fit in texture.";
    return false;
  }

  D2D1_BITMAP_PROPERTIES props =
    D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(aFormat), AlphaMode(aFormat)));
  hr = aRT->CreateBitmap(D2DIntSize(aSize), aData, aStride, props, byRef(mBitmap));

  if (FAILED(hr)) {
    gfxWarning() << "Failed to create D2D Bitmap for data. Code: " << hr;
    return false;
  }

  DrawTargetD2D::mVRAMUsageSS += GetByteSize();
  mDevice = Factory::GetDirect3D10Device();

  return true;
}
예제 #8
0
X11TextureData* X11TextureData::Create(gfx::IntSize aSize,
                                       gfx::SurfaceFormat aFormat,
                                       TextureFlags aFlags,
                                       LayersIPCChannel* aAllocator) {
  MOZ_ASSERT(aSize.width >= 0 && aSize.height >= 0);
  if (aSize.width <= 0 || aSize.height <= 0 ||
      aSize.width > XLIB_IMAGE_SIDE_SIZE_LIMIT ||
      aSize.height > XLIB_IMAGE_SIDE_SIZE_LIMIT) {
    gfxDebug() << "Asking for X11 surface of invalid size " << aSize.width
               << "x" << aSize.height;
    return nullptr;
  }
  gfxImageFormat imageFormat = SurfaceFormatToImageFormat(aFormat);
  RefPtr<gfxASurface> surface =
      gfxPlatform::GetPlatform()->CreateOffscreenSurface(aSize, imageFormat);
  if (!surface || surface->GetType() != gfxSurfaceType::Xlib) {
    NS_ERROR("creating Xlib surface failed!");
    return nullptr;
  }

  gfxXlibSurface* xlibSurface = static_cast<gfxXlibSurface*>(surface.get());

  bool crossProcess = !aAllocator->IsSameProcess();
  X11TextureData* texture = new X11TextureData(
      aSize, aFormat, !!(aFlags & TextureFlags::DEALLOCATE_CLIENT),
      crossProcess, xlibSurface);
  if (crossProcess) {
    FinishX(DefaultXDisplay());
  }

  return texture;
}
예제 #9
0
TemporaryRef<DrawTarget>
Factory::CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat)
{
  switch (aBackend) {
#ifdef WIN32
  case BACKEND_DIRECT2D:
    {
      RefPtr<DrawTargetD2D> newTarget;
      newTarget = new DrawTargetD2D();
      if (newTarget->Init(aSize, aFormat)) {
        return newTarget;
      }
      break;
    }
#elif defined XP_MACOSX || defined ANDROID || defined LINUX
#ifdef USE_SKIA
  case BACKEND_SKIA:
    {
      RefPtr<DrawTargetSkia> newTarget;
      newTarget = new DrawTargetSkia();
      if (newTarget->Init(aSize, aFormat)) {
        return newTarget;
      }
      break;
    }
#endif
#ifdef XP_MACOSX
  case BACKEND_COREGRAPHICS:
    {
      RefPtr<DrawTargetCG> newTarget;
      newTarget = new DrawTargetCG();
      if (newTarget->Init(aSize, aFormat)) {
        return newTarget;
      }
      break;
    }
#endif
#endif
  default:
    gfxDebug() << "Invalid draw target type specified.";
    return NULL;
  }

  gfxDebug() << "Failed to create DrawTarget, Type: " << aBackend << " Size: " << aSize;
  // Failed
  return NULL;
}
예제 #10
0
TemporaryRef<SourceSurface>
DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData,
                                            const IntSize &aSize,
                                            int32_t aStride,
                                            SurfaceFormat aFormat) const
{
  RefPtr<SourceSurfaceSkia> newSurf = new SourceSurfaceSkia();

  if (!newSurf->InitFromData(aData, aSize, aStride, aFormat)) {
    gfxDebug() << *this << ": Failure to create source surface from data. Size: " << aSize;
    return nullptr;
  }
    
  return newSurf;
}
예제 #11
0
// Minimum required shmem size in bytes
size_t
YCbCrImageDataDeserializerBase::ComputeMinBufferSize(const gfx::IntSize& aYSize,
        uint32_t aYStride,
        const gfx::IntSize& aCbCrSize,
        uint32_t aCbCrStride)
{
    MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0);
    if (aYSize.height <= 0 || aYSize.width <= 0 || aCbCrSize.height <= 0 || aCbCrSize.width <= 0) {
        gfxDebug() << "Non-positive YCbCr buffer size request " << aYSize.height << "x" << aYSize.width << ", " << aCbCrSize.height << "x" << aCbCrSize.width;
        return 0;
    }
    return ComputeOffset(aYSize.height, aYStride)
           + 2 * ComputeOffset(aCbCrSize.height, aCbCrStride)
           + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
}
예제 #12
0
TemporaryRef<Path>
PathBuilderD2D::Finish()
{
  if (mFigureActive) {
    mSink->EndFigure(D2D1_FIGURE_END_OPEN);
  }

  HRESULT hr = mSink->Close();
  if (FAILED(hr)) {
    gfxDebug() << "Failed to close PathSink. Code: " << hr;
    return nullptr;
  }

  return new PathD2D(mGeometry, mFigureActive, mCurrentPoint, mFillRule);
}
예제 #13
0
ShmemTextureData*
ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                         gfx::BackendType aMoz2DBackend,
                         LayersBackend aLayersBackend, TextureFlags aFlags,
                         TextureAllocationFlags aAllocFlags,
                         ClientIPCAllocator* aAllocator)
{
  MOZ_ASSERT(aAllocator);
  // Should have used CreateForYCbCr.
  MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV);

  if (!aAllocator || !aAllocator->AsShmemAllocator()) {
    return nullptr;
  }

  if (aSize.width <= 0 || aSize.height <= 0) {
    gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height;
    return nullptr;
  }

  uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat);
  if (!bufSize) {
    return nullptr;
  }

  mozilla::ipc::Shmem shm;
  if (!aAllocator->AsShmemAllocator()->AllocUnsafeShmem(bufSize, OptimalShmemType(), &shm)) {
    return nullptr;
  }

  uint8_t* buf = shm.get<uint8_t>();
  if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags, true)) {
    return nullptr;
  }

  // LAYERS_NONE must imply that we have no compositable forwarder
  MOZ_ASSERT_IF(aLayersBackend == LayersBackend::LAYERS_NONE,
                !aAllocator || !aAllocator->AsCompositableForwarder());

  bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(aFormat, aLayersBackend);

  BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasIntermediateBuffer);

  return new ShmemTextureData(descriptor, aMoz2DBackend, shm);

  return nullptr;
}
예제 #14
0
void
DrawTargetD2D1::DrawSurfaceWithShadow(SourceSurface *aSurface,
                                      const Point &aDest,
                                      const Color &aColor,
                                      const Point &aOffset,
                                      Float aSigma,
                                      CompositionOp aOperator)
{
  MarkChanged();
  mDC->SetTransform(D2D1::IdentityMatrix());
  mTransformDirty = true;

  Matrix mat;
  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, mat, ExtendMode::CLAMP);

  if (!mat.IsIdentity()) {
    gfxDebug() << *this << ": At this point complex partial uploads are not supported for Shadow surfaces.";
    return;
  }

  // Step 1, create the shadow effect.
  RefPtr<ID2D1Effect> shadowEffect;
  mDC->CreateEffect(CLSID_D2D1Shadow, byRef(shadowEffect));
  shadowEffect->SetInput(0, image);
  shadowEffect->SetValue(D2D1_SHADOW_PROP_BLUR_STANDARD_DEVIATION, aSigma);
  D2D1_VECTOR_4F color = { aColor.r, aColor.g, aColor.b, aColor.a };
  shadowEffect->SetValue(D2D1_SHADOW_PROP_COLOR, color);

  // Step 2, move the shadow effect into place.
  RefPtr<ID2D1Effect> affineTransformEffect;
  mDC->CreateEffect(CLSID_D2D12DAffineTransform, byRef(affineTransformEffect));
  affineTransformEffect->SetInputEffect(0, shadowEffect);
  D2D1_MATRIX_3X2_F matrix = D2D1::Matrix3x2F::Translation(aOffset.x, aOffset.y);
  affineTransformEffect->SetValue(D2D1_2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX, matrix);

  // Step 3, create an effect that combines shadow and bitmap in one image.
  RefPtr<ID2D1Effect> compositeEffect;
  mDC->CreateEffect(CLSID_D2D1Composite, byRef(compositeEffect));
  compositeEffect->SetInputEffect(0, affineTransformEffect);
  compositeEffect->SetInput(1, image);
  compositeEffect->SetValue(D2D1_COMPOSITE_PROP_MODE, D2DCompositionMode(aOperator));

  D2D1_POINT_2F surfPoint = D2DPoint(aDest);
  mDC->DrawImage(compositeEffect, &surfPoint, nullptr, D2D1_INTERPOLATION_MODE_LINEAR, D2DCompositionMode(aOperator));
}
예제 #15
0
void
DrawTargetD2D1::Fill(const Path *aPath,
                     const Pattern &aPattern,
                     const DrawOptions &aOptions)
{
  if (aPath->GetBackendType() != BackendType::DIRECT2D) {
    gfxDebug() << *this << ": Ignoring drawing call for incompatible path.";
    return;
  }
  const PathD2D *d2dPath = static_cast<const PathD2D*>(aPath);

  PrepareForDrawing(aOptions.mCompositionOp, aPattern);

  RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);

  mDC->FillGeometry(d2dPath->mGeometry, brush);

  FinalizeDrawing(aOptions.mCompositionOp, aPattern);
}
예제 #16
0
void
DrawTargetD2D1::CopySurface(SourceSurface *aSurface,
                            const IntRect &aSourceRect,
                            const IntPoint &aDestination)
{
  MarkChanged();

  mDC->SetTransform(D2D1::IdentityMatrix());
  mTransformDirty = true;

  Matrix mat;
  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, mat, ExtendMode::CLAMP);

  if (!mat.IsIdentity()) {
    gfxDebug() << *this << ": At this point complex partial uploads are not supported for CopySurface.";
    return;
  }

  mDC->DrawImage(image, D2D1::Point2F(Float(aDestination.x), Float(aDestination.y)),
                 D2D1::RectF(Float(aSourceRect.x), Float(aSourceRect.y), 
                             Float(aSourceRect.XMost()), Float(aSourceRect.YMost())),
                 D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2D1_COMPOSITE_MODE_BOUNDED_SOURCE_COPY);
}
예제 #17
0
void
DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
                            const Rect &aDest,
                            const Rect &aSource,
                            const DrawSurfaceOptions &aSurfOptions,
                            const DrawOptions &aOptions)
{
  RefPtr<SourceSurface> dataSurface;

  if (!(aSurface->GetType() == SurfaceType::SKIA || aSurface->GetType() == SurfaceType::DATA)) {
    dataSurface = aSurface->GetDataSurface();
    if (!dataSurface) {
      gfxDebug() << *this << ": DrawSurface() can't draw surface";
      return;
    }
    aSurface = dataSurface.get();
  }

  if (aSource.IsEmpty()) {
    return;
  }

  MarkChanged();

  SkRect destRect = RectToSkRect(aDest);
  SkRect sourceRect = RectToSkRect(aSource);

  TempBitmap bitmap = GetBitmapForSurface(aSurface);
 
  AutoPaintSetup paint(mCanvas.get(), aOptions, &aDest);
  if (aSurfOptions.mFilter == Filter::POINT) {
    paint.mPaint.setFilterLevel(SkPaint::kNone_FilterLevel);
  }

  mCanvas->drawBitmapRectToRect(bitmap.mBitmap, &sourceRect, destRect, &paint.mPaint);
}
TemporaryRef<DataSourceSurface>
SourceSurfaceD2DTarget::GetDataSurface()
{
  RefPtr<DataSourceSurfaceD2DTarget> dataSurf =
    new DataSourceSurfaceD2DTarget();

  D3D10_TEXTURE2D_DESC desc;
  mTexture->GetDesc(&desc);

  desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
  desc.Usage = D3D10_USAGE_STAGING;
  desc.BindFlags = 0;
  desc.MiscFlags = 0;

  HRESULT hr = Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, byRef(dataSurf->mTexture));

  if (FAILED(hr)) {
    gfxDebug() << "Failed to create staging texture for SourceSurface. Code: " << hr;
    return nullptr;
  }
  Factory::GetDirect3D10Device()->CopyResource(dataSurf->mTexture, mTexture);

  return dataSurf;
}
예제 #19
0
TemporaryRef<ID2D1Brush>
DrawTargetD2D1::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
{
  if (!IsPatternSupportedByD2D(aPattern)) {
    RefPtr<ID2D1SolidColorBrush> colBrush;
    mDC->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), byRef(colBrush));
    return colBrush;
  }

  if (aPattern.GetType() == PatternType::COLOR) {
    RefPtr<ID2D1SolidColorBrush> colBrush;
    Color color = static_cast<const ColorPattern*>(&aPattern)->mColor;
    mDC->CreateSolidColorBrush(D2D1::ColorF(color.r, color.g,
                                            color.b, color.a),
                               D2D1::BrushProperties(aAlpha),
                               byRef(colBrush));
    return colBrush;
  } else if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) {
    RefPtr<ID2D1LinearGradientBrush> gradBrush;
    const LinearGradientPattern *pat =
      static_cast<const LinearGradientPattern*>(&aPattern);

    GradientStopsD2D *stops = static_cast<GradientStopsD2D*>(pat->mStops.get());

    if (!stops) {
      gfxDebug() << "No stops specified for gradient pattern.";
      return nullptr;
    }

    if (pat->mBegin == pat->mEnd) {
      RefPtr<ID2D1SolidColorBrush> colBrush;
      uint32_t stopCount = stops->mStopCollection->GetGradientStopCount();
      vector<D2D1_GRADIENT_STOP> d2dStops(stopCount);
      stops->mStopCollection->GetGradientStops(&d2dStops.front(), stopCount);
      mDC->CreateSolidColorBrush(d2dStops.back().color,
                                 D2D1::BrushProperties(aAlpha),
                                 byRef(colBrush));
      return colBrush;
    }

    mDC->CreateLinearGradientBrush(D2D1::LinearGradientBrushProperties(D2DPoint(pat->mBegin),
                                                                       D2DPoint(pat->mEnd)),
                                   D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
                                   stops->mStopCollection,
                                   byRef(gradBrush));
    return gradBrush;
  } else if (aPattern.GetType() == PatternType::RADIAL_GRADIENT) {
    RefPtr<ID2D1RadialGradientBrush> gradBrush;
    const RadialGradientPattern *pat =
      static_cast<const RadialGradientPattern*>(&aPattern);

    GradientStopsD2D *stops = static_cast<GradientStopsD2D*>(pat->mStops.get());

    if (!stops) {
      gfxDebug() << "No stops specified for gradient pattern.";
      return nullptr;
    }

    // This will not be a complex radial gradient brush.
    mDC->CreateRadialGradientBrush(
      D2D1::RadialGradientBrushProperties(D2DPoint(pat->mCenter2),
                                          D2DPoint(pat->mCenter1 - pat->mCenter2),
                                          pat->mRadius2, pat->mRadius2),
      D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
      stops->mStopCollection,
      byRef(gradBrush));

    return gradBrush;
  } else if (aPattern.GetType() == PatternType::SURFACE) {
    const SurfacePattern *pat =
      static_cast<const SurfacePattern*>(&aPattern);

    if (!pat->mSurface) {
      gfxDebug() << "No source surface specified for surface pattern";
      return nullptr;
    }


    Matrix mat = pat->mMatrix;
    
    RefPtr<ID2D1ImageBrush> imageBrush;
    RefPtr<ID2D1Image> image = GetImageForSurface(pat->mSurface, mat, pat->mExtendMode);
    mDC->CreateImageBrush(image,
                          D2D1::ImageBrushProperties(D2D1::RectF(0, 0,
                                                                  Float(pat->mSurface->GetSize().width),
                                                                  Float(pat->mSurface->GetSize().height)),
                                  D2DExtend(pat->mExtendMode), D2DExtend(pat->mExtendMode),
                                  D2DInterpolationMode(pat->mFilter)),
                          D2D1::BrushProperties(aAlpha, D2DMatrix(mat)),
                          byRef(imageBrush));
    return imageBrush;
  }

  gfxWarning() << "Invalid pattern type detected.";
  return nullptr;
}
예제 #20
0
void
DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
                           const GlyphBuffer &aBuffer,
                           const Pattern &aPattern,
                           const DrawOptions &aOptions,
                           const GlyphRenderingOptions *aRenderingOptions)
{
  if (aFont->GetType() != FontType::DWRITE) {
    gfxDebug() << *this << ": Ignoring drawing call for incompatible font.";
    return;
  }

  ScaledFontDWrite *font = static_cast<ScaledFontDWrite*>(aFont);

  IDWriteRenderingParams *params = nullptr;
  if (aRenderingOptions) {
    if (aRenderingOptions->GetType() != FontType::DWRITE) {
      gfxDebug() << *this << ": Ignoring incompatible GlyphRenderingOptions.";
      // This should never happen.
      MOZ_ASSERT(false);
    } else {
      params = static_cast<const GlyphRenderingOptionsDWrite*>(aRenderingOptions)->mParams;
    }
  }

  AntialiasMode aaMode = font->GetDefaultAAMode();

  if (aOptions.mAntialiasMode != AntialiasMode::DEFAULT) {
    aaMode = aOptions.mAntialiasMode;
  }

  PrepareForDrawing(aOptions.mCompositionOp, aPattern);

  bool forceClearType = false;
  if (mFormat == SurfaceFormat::B8G8R8A8 && mPermitSubpixelAA &&
      aOptions.mCompositionOp == CompositionOp::OP_OVER && aaMode == AntialiasMode::SUBPIXEL) {
    forceClearType = true;    
  }


  D2D1_TEXT_ANTIALIAS_MODE d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;

  switch (aaMode) {
  case AntialiasMode::NONE:
    d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
    break;
  case AntialiasMode::GRAY:
    d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
    break;
  case AntialiasMode::SUBPIXEL:
    d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
    break;
  default:
    d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
  }

  if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE &&
      mFormat != SurfaceFormat::B8G8R8X8 && !forceClearType) {
    d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
  }

  mDC->SetTextAntialiasMode(d2dAAMode);

  if (params != mTextRenderingParams) {
    mDC->SetTextRenderingParams(params);
    mTextRenderingParams = params;
  }

  RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);

  AutoDWriteGlyphRun autoRun;
  DWriteGlyphRunFromGlyphs(aBuffer, font, &autoRun);

  if (brush) {
    mDC->DrawGlyphRun(D2D1::Point2F(), &autoRun, brush);
  }

  FinalizeDrawing(aOptions.mCompositionOp, aPattern);
}