Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/gfx/HelpersSkia.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef MOZILLA_GFX_HELPERSSKIA_H_
8
#define MOZILLA_GFX_HELPERSSKIA_H_
9
10
#include "2D.h"
11
#include "skia/include/core/SkCanvas.h"
12
#include "skia/include/effects/SkDashPathEffect.h"
13
#include "skia/include/core/SkShader.h"
14
#include "mozilla/Assertions.h"
15
#include <vector>
16
#include "nsDebug.h"
17
18
namespace mozilla {
19
namespace gfx {
20
21
static inline SkColorType
22
GfxFormatToSkiaColorType(SurfaceFormat format)
23
{
24
  switch (format)
25
  {
26
    case SurfaceFormat::B8G8R8A8:
27
      return kBGRA_8888_SkColorType;
28
    case SurfaceFormat::B8G8R8X8:
29
      // We probably need to do something here.
30
      return kBGRA_8888_SkColorType;
31
    case SurfaceFormat::R5G6B5_UINT16:
32
      return kRGB_565_SkColorType;
33
    case SurfaceFormat::A8:
34
      return kAlpha_8_SkColorType;
35
    default:
36
      return kRGBA_8888_SkColorType;
37
  }
38
}
39
40
static inline SurfaceFormat
41
SkiaColorTypeToGfxFormat(SkColorType aColorType, SkAlphaType aAlphaType = kPremul_SkAlphaType)
42
0
{
43
0
  switch (aColorType)
44
0
  {
45
0
    case kBGRA_8888_SkColorType:
46
0
      return aAlphaType == kOpaque_SkAlphaType ?
47
0
               SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
48
0
    case kRGB_565_SkColorType:
49
0
      return SurfaceFormat::R5G6B5_UINT16;
50
0
    case kAlpha_8_SkColorType:
51
0
      return SurfaceFormat::A8;
52
0
    default:
53
0
      return SurfaceFormat::B8G8R8A8;
54
0
  }
55
0
}
56
57
static inline SkAlphaType
58
GfxFormatToSkiaAlphaType(SurfaceFormat format)
59
{
60
  switch (format)
61
  {
62
    case SurfaceFormat::B8G8R8X8:
63
    case SurfaceFormat::R5G6B5_UINT16:
64
      return kOpaque_SkAlphaType;
65
    default:
66
      return kPremul_SkAlphaType;
67
  }
68
}
69
70
static inline SkImageInfo
71
MakeSkiaImageInfo(const IntSize& aSize, SurfaceFormat aFormat)
72
0
{
73
0
  return SkImageInfo::Make(aSize.width, aSize.height,
74
0
                           GfxFormatToSkiaColorType(aFormat),
75
0
                           GfxFormatToSkiaAlphaType(aFormat));
76
0
}
77
78
static inline void
79
GfxMatrixToSkiaMatrix(const Matrix& mat, SkMatrix& retval)
80
0
{
81
0
    retval.setAll(SkFloatToScalar(mat._11), SkFloatToScalar(mat._21), SkFloatToScalar(mat._31),
82
0
                  SkFloatToScalar(mat._12), SkFloatToScalar(mat._22), SkFloatToScalar(mat._32),
83
0
                  0, 0, SK_Scalar1);
84
0
}
85
86
static inline void
87
GfxMatrixToSkiaMatrix(const Matrix4x4& aMatrix, SkMatrix& aResult)
88
0
{
89
0
  aResult.setAll(SkFloatToScalar(aMatrix._11), SkFloatToScalar(aMatrix._21), SkFloatToScalar(aMatrix._41),
90
0
                 SkFloatToScalar(aMatrix._12), SkFloatToScalar(aMatrix._22), SkFloatToScalar(aMatrix._42),
91
0
                 SkFloatToScalar(aMatrix._14), SkFloatToScalar(aMatrix._24), SkFloatToScalar(aMatrix._44));
92
0
}
93
94
static inline SkPaint::Cap
95
CapStyleToSkiaCap(CapStyle aCap)
96
0
{
97
0
  switch (aCap)
98
0
  {
99
0
    case CapStyle::BUTT:
100
0
      return SkPaint::kButt_Cap;
101
0
    case CapStyle::ROUND:
102
0
      return SkPaint::kRound_Cap;
103
0
    case CapStyle::SQUARE:
104
0
      return SkPaint::kSquare_Cap;
105
0
  }
106
0
  return SkPaint::kDefault_Cap;
107
0
}
108
109
static inline SkPaint::Join
110
JoinStyleToSkiaJoin(JoinStyle aJoin)
111
0
{
112
0
  switch (aJoin)
113
0
  {
114
0
    case JoinStyle::BEVEL:
115
0
      return SkPaint::kBevel_Join;
116
0
    case JoinStyle::ROUND:
117
0
      return SkPaint::kRound_Join;
118
0
    case JoinStyle::MITER:
119
0
    case JoinStyle::MITER_OR_BEVEL:
120
0
      return SkPaint::kMiter_Join;
121
0
  }
122
0
  return SkPaint::kDefault_Join;
123
0
}
124
125
static inline bool
126
StrokeOptionsToPaint(SkPaint& aPaint, const StrokeOptions &aOptions)
127
0
{
128
0
  // Skia renders 0 width strokes with a width of 1 (and in black),
129
0
  // so we should just skip the draw call entirely.
130
0
  // Skia does not handle non-finite line widths.
131
0
  if (!aOptions.mLineWidth || !IsFinite(aOptions.mLineWidth)) {
132
0
    return false;
133
0
  }
134
0
  aPaint.setStrokeWidth(SkFloatToScalar(aOptions.mLineWidth));
135
0
  aPaint.setStrokeMiter(SkFloatToScalar(aOptions.mMiterLimit));
136
0
  aPaint.setStrokeCap(CapStyleToSkiaCap(aOptions.mLineCap));
137
0
  aPaint.setStrokeJoin(JoinStyleToSkiaJoin(aOptions.mLineJoin));
138
0
139
0
  if (aOptions.mDashLength > 0) {
140
0
    // Skia only supports dash arrays that are multiples of 2.
141
0
    uint32_t dashCount;
142
0
143
0
    if (aOptions.mDashLength % 2 == 0) {
144
0
      dashCount = aOptions.mDashLength;
145
0
    } else {
146
0
      dashCount = aOptions.mDashLength * 2;
147
0
    }
148
0
149
0
    std::vector<SkScalar> pattern;
150
0
    pattern.resize(dashCount);
151
0
152
0
    for (uint32_t i = 0; i < dashCount; i++) {
153
0
      pattern[i] = SkFloatToScalar(aOptions.mDashPattern[i % aOptions.mDashLength]);
154
0
    }
155
0
156
0
    sk_sp<SkPathEffect> dash = SkDashPathEffect::Make(&pattern.front(),
157
0
                                                      dashCount,
158
0
                                                      SkFloatToScalar(aOptions.mDashOffset));
159
0
    aPaint.setPathEffect(dash);
160
0
  }
161
0
162
0
  aPaint.setStyle(SkPaint::kStroke_Style);
163
0
  return true;
164
0
}
165
166
static inline SkBlendMode
167
GfxOpToSkiaOp(CompositionOp op)
168
0
{
169
0
  switch (op)
170
0
  {
171
0
    case CompositionOp::OP_OVER:
172
0
      return SkBlendMode::kSrcOver;
173
0
    case CompositionOp::OP_ADD:
174
0
      return SkBlendMode::kPlus;
175
0
    case CompositionOp::OP_ATOP:
176
0
      return SkBlendMode::kSrcATop;
177
0
    case CompositionOp::OP_OUT:
178
0
      return SkBlendMode::kSrcOut;
179
0
    case CompositionOp::OP_IN:
180
0
      return SkBlendMode::kSrcIn;
181
0
    case CompositionOp::OP_SOURCE:
182
0
      return SkBlendMode::kSrc;
183
0
    case CompositionOp::OP_DEST_IN:
184
0
      return SkBlendMode::kDstIn;
185
0
    case CompositionOp::OP_DEST_OUT:
186
0
      return SkBlendMode::kDstOut;
187
0
    case CompositionOp::OP_DEST_OVER:
188
0
      return SkBlendMode::kDstOver;
189
0
    case CompositionOp::OP_DEST_ATOP:
190
0
      return SkBlendMode::kDstATop;
191
0
    case CompositionOp::OP_XOR:
192
0
      return SkBlendMode::kXor;
193
0
    case CompositionOp::OP_MULTIPLY:
194
0
      return SkBlendMode::kMultiply;
195
0
    case CompositionOp::OP_SCREEN:
196
0
      return SkBlendMode::kScreen;
197
0
    case CompositionOp::OP_OVERLAY:
198
0
      return SkBlendMode::kOverlay;
199
0
    case CompositionOp::OP_DARKEN:
200
0
      return SkBlendMode::kDarken;
201
0
    case CompositionOp::OP_LIGHTEN:
202
0
      return SkBlendMode::kLighten;
203
0
    case CompositionOp::OP_COLOR_DODGE:
204
0
      return SkBlendMode::kColorDodge;
205
0
    case CompositionOp::OP_COLOR_BURN:
206
0
      return SkBlendMode::kColorBurn;
207
0
    case CompositionOp::OP_HARD_LIGHT:
208
0
      return SkBlendMode::kHardLight;
209
0
    case CompositionOp::OP_SOFT_LIGHT:
210
0
      return SkBlendMode::kSoftLight;
211
0
    case CompositionOp::OP_DIFFERENCE:
212
0
      return SkBlendMode::kDifference;
213
0
    case CompositionOp::OP_EXCLUSION:
214
0
      return SkBlendMode::kExclusion;
215
0
    case CompositionOp::OP_HUE:
216
0
      return SkBlendMode::kHue;
217
0
    case CompositionOp::OP_SATURATION:
218
0
      return SkBlendMode::kSaturation;
219
0
    case CompositionOp::OP_COLOR:
220
0
      return SkBlendMode::kColor;
221
0
    case CompositionOp::OP_LUMINOSITY:
222
0
      return SkBlendMode::kLuminosity;
223
0
    default:
224
0
      return SkBlendMode::kSrcOver;
225
0
  }
226
0
}
227
228
/* There's quite a bit of inconsistency about
229
 * whether float colors should be rounded with .5f.
230
 * We choose to do it to match cairo which also
231
 * happens to match the Direct3D specs */
232
static inline U8CPU ColorFloatToByte(Float color)
233
0
{
234
0
  //XXX: do a better job converting to int
235
0
  return U8CPU(color*255.f + .5f);
236
0
};
237
238
static inline SkColor ColorToSkColor(const Color &color, Float aAlpha)
239
0
{
240
0
  return SkColorSetARGB(ColorFloatToByte(color.a*aAlpha), ColorFloatToByte(color.r),
241
0
                        ColorFloatToByte(color.g), ColorFloatToByte(color.b));
242
0
}
243
244
static inline SkPoint
245
PointToSkPoint(const Point &aPoint)
246
0
{
247
0
  return SkPoint::Make(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
248
0
}
249
250
static inline SkRect
251
RectToSkRect(const Rect& aRect)
252
0
{
253
0
  return SkRect::MakeXYWH(SkFloatToScalar(aRect.X()), SkFloatToScalar(aRect.Y()),
254
0
                          SkFloatToScalar(aRect.Width()), SkFloatToScalar(aRect.Height()));
255
0
}
256
257
static inline SkRect
258
IntRectToSkRect(const IntRect& aRect)
259
0
{
260
0
  return SkRect::MakeXYWH(SkIntToScalar(aRect.X()), SkIntToScalar(aRect.Y()),
261
0
                          SkIntToScalar(aRect.Width()), SkIntToScalar(aRect.Height()));
262
0
}
263
264
static inline SkIRect
265
RectToSkIRect(const Rect& aRect)
266
0
{
267
0
  return SkIRect::MakeXYWH(int32_t(aRect.X()), int32_t(aRect.Y()),
268
0
                           int32_t(aRect.Width()), int32_t(aRect.Height()));
269
0
}
270
271
static inline SkIRect
272
IntRectToSkIRect(const IntRect& aRect)
273
0
{
274
0
  return SkIRect::MakeXYWH(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
275
0
}
276
277
static inline IntRect
278
SkIRectToIntRect(const SkIRect& aRect)
279
0
{
280
0
  return IntRect(aRect.x(), aRect.y(), aRect.width(), aRect.height());
281
0
}
282
283
static inline Point
284
SkPointToPoint(const SkPoint &aPoint)
285
0
{
286
0
  return Point(SkScalarToFloat(aPoint.x()), SkScalarToFloat(aPoint.y()));
287
0
}
288
289
static inline Rect
290
SkRectToRect(const SkRect &aRect)
291
0
{
292
0
  return Rect(SkScalarToFloat(aRect.x()), SkScalarToFloat(aRect.y()),
293
0
              SkScalarToFloat(aRect.width()), SkScalarToFloat(aRect.height()));
294
0
}
295
296
static inline SkShader::TileMode
297
ExtendModeToTileMode(ExtendMode aMode, Axis aAxis)
298
0
{
299
0
  switch (aMode)
300
0
  {
301
0
    case ExtendMode::CLAMP:
302
0
      return SkShader::kClamp_TileMode;
303
0
    case ExtendMode::REPEAT:
304
0
      return SkShader::kRepeat_TileMode;
305
0
    case ExtendMode::REFLECT:
306
0
      return SkShader::kMirror_TileMode;
307
0
    case ExtendMode::REPEAT_X:
308
0
    {
309
0
      return aAxis == Axis::X_AXIS
310
0
             ? SkShader::kRepeat_TileMode
311
0
             : SkShader::kClamp_TileMode;
312
0
    }
313
0
    case ExtendMode::REPEAT_Y:
314
0
    {
315
0
      return aAxis == Axis::Y_AXIS
316
0
             ? SkShader::kRepeat_TileMode
317
0
             : SkShader::kClamp_TileMode;
318
0
    }
319
0
  }
320
0
  return SkShader::kClamp_TileMode;
321
0
}
322
323
static inline SkPaint::Hinting
324
GfxHintingToSkiaHinting(FontHinting aHinting)
325
0
{
326
0
  switch (aHinting) {
327
0
    case FontHinting::NONE:
328
0
      return SkPaint::kNo_Hinting;
329
0
    case FontHinting::LIGHT:
330
0
      return SkPaint::kSlight_Hinting;
331
0
    case FontHinting::NORMAL:
332
0
      return SkPaint::kNormal_Hinting;
333
0
    case FontHinting::FULL:
334
0
      return SkPaint::kFull_Hinting;
335
0
  }
336
0
  return SkPaint::kNormal_Hinting;
337
0
}
338
339
static inline FillRule GetFillRule(SkPath::FillType aFillType)
340
0
{
341
0
  switch (aFillType)
342
0
  {
343
0
  case SkPath::kWinding_FillType:
344
0
    return FillRule::FILL_WINDING;
345
0
  case SkPath::kEvenOdd_FillType:
346
0
    return FillRule::FILL_EVEN_ODD;
347
0
  case SkPath::kInverseWinding_FillType:
348
0
  case SkPath::kInverseEvenOdd_FillType:
349
0
  default:
350
0
    NS_WARNING("Unsupported fill type\n");
351
0
    break;
352
0
  }
353
0
354
0
  return FillRule::FILL_EVEN_ODD;
355
0
}
356
357
/**
358
 * Returns true if the canvas is backed by pixels.  Returns false if the canvas
359
 * wraps an SkPDFDocument, for example.
360
 *
361
 * Note: It is not clear whether the test used to implement this function may
362
 * result in it returning false in some circumstances even when the canvas
363
 * _is_ pixel backed.  In other words maybe it is possible for such a canvas to
364
 * have kUnknown_SkPixelGeometry?
365
 */
366
static inline bool IsBackedByPixels(const SkCanvas* aCanvas)
367
0
{
368
0
  SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
369
0
  if (!aCanvas->getProps(&props) ||
370
0
      props.pixelGeometry() == kUnknown_SkPixelGeometry) {
371
0
    return false;
372
0
  }
373
0
  return true;
374
0
}
375
376
} // namespace gfx
377
} // namespace mozilla
378
379
#endif /* MOZILLA_GFX_HELPERSSKIA_H_ */