1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Corporation code.
16 : *
17 : * The Initial Developer of the Original Code is Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2011
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Matt Woodrow <mwoodrow@mozilla.com>
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "DrawTargetSkia.h"
39 : #include "SourceSurfaceSkia.h"
40 : #include "ScaledFontBase.h"
41 : #include "skia/SkDevice.h"
42 : #include "skia/SkTypeface.h"
43 : #include "skia/SkGradientShader.h"
44 : #include "skia/SkBlurDrawLooper.h"
45 : #include "skia/SkBlurMaskFilter.h"
46 : #include "skia/SkColorFilter.h"
47 : #include "skia/SkLayerRasterizer.h"
48 : #include "skia/SkLayerDrawLooper.h"
49 : #include "skia/SkDashPathEffect.h"
50 : #include "Logging.h"
51 : #include "HelpersSkia.h"
52 : #include "Tools.h"
53 : #include <algorithm>
54 :
55 : #ifdef ANDROID
56 : # define USE_SOFT_CLIPPING false
57 : #else
58 : # define USE_SOFT_CLIPPING true
59 : #endif
60 :
61 : namespace mozilla {
62 : namespace gfx {
63 :
64 0 : SkColor ColorToSkColor(const Color &color, Float aAlpha)
65 : {
66 : //XXX: do a better job converting to int
67 0 : return SkColorSetARGB(color.a*aAlpha*255.0, color.r*255.0, color.g*255.0, color.b*255.0);
68 : }
69 :
70 : class GradientStopsSkia : public GradientStops
71 0 : {
72 : public:
73 0 : GradientStopsSkia(const std::vector<GradientStop>& aStops, uint32_t aNumStops, ExtendMode aExtendMode)
74 : : mCount(aNumStops)
75 0 : , mExtendMode(aExtendMode)
76 : {
77 0 : if (mCount == 0) {
78 0 : return;
79 : }
80 :
81 : // Skia gradients always require a stop at 0.0 and 1.0, insert these if
82 : // we don't have them.
83 0 : uint32_t shift = 0;
84 0 : if (aStops[0].offset != 0) {
85 0 : mCount++;
86 0 : shift = 1;
87 : }
88 0 : if (aStops[aNumStops-1].offset != 1) {
89 0 : mCount++;
90 : }
91 0 : mColors.resize(mCount);
92 0 : mPositions.resize(mCount);
93 0 : if (aStops[0].offset != 0) {
94 0 : mColors[0] = ColorToSkColor(aStops[0].color, 1.0);
95 0 : mPositions[0] = 0;
96 : }
97 0 : for (uint32_t i = 0; i < aNumStops; i++) {
98 0 : mColors[i + shift] = ColorToSkColor(aStops[i].color, 1.0);
99 0 : mPositions[i + shift] = SkFloatToScalar(aStops[i].offset);
100 : }
101 0 : if (aStops[aNumStops-1].offset != 1) {
102 0 : mColors[mCount-1] = ColorToSkColor(aStops[aNumStops-1].color, 1.0);
103 0 : mPositions[mCount-1] = SK_Scalar1;
104 : }
105 : }
106 :
107 0 : BackendType GetBackendType() const { return BACKEND_SKIA; }
108 :
109 : std::vector<SkColor> mColors;
110 : std::vector<SkScalar> mPositions;
111 : int mCount;
112 : ExtendMode mExtendMode;
113 : };
114 :
115 : SkXfermode::Mode
116 0 : GfxOpToSkiaOp(CompositionOp op)
117 : {
118 0 : switch (op)
119 : {
120 : case OP_OVER:
121 0 : return SkXfermode::kSrcOver_Mode;
122 : case OP_ADD:
123 0 : return SkXfermode::kPlus_Mode;
124 : case OP_ATOP:
125 0 : return SkXfermode::kSrcATop_Mode;
126 : case OP_OUT:
127 0 : return SkXfermode::kSrcOut_Mode;
128 : case OP_IN:
129 0 : return SkXfermode::kSrcIn_Mode;
130 : case OP_SOURCE:
131 0 : return SkXfermode::kSrc_Mode;
132 : case OP_DEST_IN:
133 0 : return SkXfermode::kDstIn_Mode;
134 : case OP_DEST_OUT:
135 0 : return SkXfermode::kDstOut_Mode;
136 : case OP_DEST_OVER:
137 0 : return SkXfermode::kDstOver_Mode;
138 : case OP_DEST_ATOP:
139 0 : return SkXfermode::kDstATop_Mode;
140 : case OP_XOR:
141 0 : return SkXfermode::kXor_Mode;
142 : case OP_COUNT:
143 0 : return SkXfermode::kSrcOver_Mode;
144 : }
145 0 : return SkXfermode::kSrcOver_Mode;
146 : }
147 :
148 :
149 : SkRect
150 0 : RectToSkRect(const Rect& aRect)
151 : {
152 : return SkRect::MakeXYWH(SkFloatToScalar(aRect.x), SkFloatToScalar(aRect.y),
153 0 : SkFloatToScalar(aRect.width), SkFloatToScalar(aRect.height));
154 : }
155 :
156 : SkRect
157 0 : IntRectToSkRect(const IntRect& aRect)
158 : {
159 : return SkRect::MakeXYWH(SkIntToScalar(aRect.x), SkIntToScalar(aRect.y),
160 0 : SkIntToScalar(aRect.width), SkIntToScalar(aRect.height));
161 : }
162 :
163 : SkIRect
164 0 : RectToSkIRect(const Rect& aRect)
165 : {
166 0 : return SkIRect::MakeXYWH(aRect.x, aRect.y, aRect.width, aRect.height);
167 : }
168 :
169 : SkIRect
170 0 : IntRectToSkIRect(const IntRect& aRect)
171 : {
172 0 : return SkIRect::MakeXYWH(aRect.x, aRect.y, aRect.width, aRect.height);
173 : }
174 :
175 :
176 0 : DrawTargetSkia::DrawTargetSkia()
177 : {
178 0 : }
179 :
180 0 : DrawTargetSkia::~DrawTargetSkia()
181 : {
182 0 : if (mSnapshots.size()) {
183 0 : for (std::vector<SourceSurfaceSkia*>::iterator iter = mSnapshots.begin();
184 0 : iter != mSnapshots.end(); iter++) {
185 0 : (*iter)->DrawTargetDestroyed();
186 : }
187 : // All snapshots will now have copied data.
188 0 : mSnapshots.clear();
189 : }
190 0 : }
191 :
192 : TemporaryRef<SourceSurface>
193 0 : DrawTargetSkia::Snapshot()
194 : {
195 0 : RefPtr<SourceSurfaceSkia> source = new SourceSurfaceSkia();
196 0 : if (!source->InitWithBitmap(mBitmap, mFormat, this)) {
197 0 : return NULL;
198 : }
199 0 : AppendSnapshot(source);
200 0 : return source;
201 : }
202 :
203 : SkShader::TileMode
204 0 : ExtendModeToTileMode(ExtendMode aMode)
205 : {
206 0 : switch (aMode)
207 : {
208 : case EXTEND_CLAMP:
209 0 : return SkShader::kClamp_TileMode;
210 : case EXTEND_REPEAT:
211 0 : return SkShader::kRepeat_TileMode;
212 : case EXTEND_REFLECT:
213 0 : return SkShader::kMirror_TileMode;
214 : }
215 0 : return SkShader::kClamp_TileMode;
216 : }
217 :
218 0 : void SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, Float aAlpha = 1.0)
219 : {
220 0 : switch (aPattern.GetType()) {
221 : case PATTERN_COLOR: {
222 0 : Color color = static_cast<const ColorPattern&>(aPattern).mColor;
223 0 : aPaint.setColor(ColorToSkColor(color, aAlpha));
224 0 : break;
225 : }
226 : case PATTERN_LINEAR_GRADIENT: {
227 0 : const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
228 0 : GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
229 0 : SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);
230 :
231 0 : if (stops->mCount >= 2) {
232 : SkPoint points[2];
233 0 : points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y));
234 0 : points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y));
235 :
236 : SkShader* shader = SkGradientShader::CreateLinear(points,
237 0 : &stops->mColors.front(),
238 0 : &stops->mPositions.front(),
239 : stops->mCount,
240 0 : mode);
241 : SkMatrix mat;
242 0 : GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
243 0 : shader->setLocalMatrix(mat);
244 0 : SkSafeUnref(aPaint.setShader(shader));
245 : } else {
246 0 : aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
247 : }
248 0 : break;
249 : }
250 : case PATTERN_RADIAL_GRADIENT: {
251 0 : const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern);
252 0 : GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
253 0 : SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);
254 :
255 0 : if (stops->mCount >= 2) {
256 : SkPoint points[2];
257 0 : points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y));
258 0 : points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y));
259 :
260 : SkShader* shader = SkGradientShader::CreateTwoPointRadial(points[0],
261 : SkFloatToScalar(pat.mRadius1),
262 : points[1],
263 : SkFloatToScalar(pat.mRadius2),
264 0 : &stops->mColors.front(),
265 0 : &stops->mPositions.front(),
266 : stops->mCount,
267 0 : mode);
268 : SkMatrix mat;
269 0 : GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
270 0 : shader->setLocalMatrix(mat);
271 0 : SkSafeUnref(aPaint.setShader(shader));
272 : } else {
273 0 : aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
274 : }
275 0 : break;
276 : }
277 : case PATTERN_SURFACE: {
278 0 : const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
279 0 : const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(pat.mSurface.get())->GetBitmap();
280 :
281 0 : SkShader::TileMode mode = ExtendModeToTileMode(pat.mExtendMode);
282 0 : SkShader* shader = SkShader::CreateBitmapShader(bitmap, mode, mode);
283 : SkMatrix mat;
284 0 : GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
285 0 : shader->setLocalMatrix(mat);
286 0 : SkSafeUnref(aPaint.setShader(shader));
287 0 : if (pat.mFilter == FILTER_POINT) {
288 0 : aPaint.setFilterBitmap(false);
289 : }
290 0 : break;
291 : }
292 : }
293 0 : }
294 :
295 : struct AutoPaintSetup {
296 0 : AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Pattern& aPattern)
297 0 : : mNeedsRestore(false), mAlpha(1.0)
298 : {
299 0 : Init(aCanvas, aOptions);
300 0 : SetPaintPattern(mPaint, aPattern, mAlpha);
301 0 : }
302 :
303 0 : AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions)
304 0 : : mNeedsRestore(false), mAlpha(1.0)
305 : {
306 0 : Init(aCanvas, aOptions);
307 0 : }
308 :
309 0 : ~AutoPaintSetup()
310 0 : {
311 0 : if (mNeedsRestore) {
312 0 : mCanvas->restore();
313 : }
314 0 : }
315 :
316 0 : void Init(SkCanvas *aCanvas, const DrawOptions& aOptions)
317 : {
318 0 : mPaint.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
319 0 : mCanvas = aCanvas;
320 :
321 : //TODO: Can we set greyscale somehow?
322 0 : if (aOptions.mAntialiasMode != AA_NONE) {
323 0 : mPaint.setAntiAlias(true);
324 : } else {
325 0 : mPaint.setAntiAlias(false);
326 : }
327 :
328 0 : NS_ASSERTION(aOptions.mSnapping == SNAP_NONE, "Pixel snapping not supported yet!");
329 :
330 : // TODO: We could skip the temporary for operator_source and just
331 : // clear the clip rect. The other operators would be harder
332 : // but could be worth it to skip pushing a group.
333 0 : if (!IsOperatorBoundByMask(aOptions.mCompositionOp)) {
334 0 : mPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
335 0 : SkPaint temp;
336 0 : temp.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
337 0 : temp.setAlpha(aOptions.mAlpha*255);
338 : //TODO: Get a rect here
339 0 : mCanvas->saveLayer(NULL, &temp);
340 0 : mNeedsRestore = true;
341 : } else {
342 0 : mPaint.setAlpha(aOptions.mAlpha*255.0);
343 0 : mAlpha = aOptions.mAlpha;
344 : }
345 0 : mPaint.setFilterBitmap(true);
346 0 : }
347 :
348 : // TODO: Maybe add an operator overload to access this easier?
349 : SkPaint mPaint;
350 : bool mNeedsRestore;
351 : SkCanvas* mCanvas;
352 : Float mAlpha;
353 : };
354 :
355 : void
356 0 : DrawTargetSkia::Flush()
357 : {
358 0 : }
359 :
360 : void
361 0 : DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
362 : const Rect &aDest,
363 : const Rect &aSource,
364 : const DrawSurfaceOptions &aSurfOptions,
365 : const DrawOptions &aOptions)
366 : {
367 0 : if (aSurface->GetType() != SURFACE_SKIA) {
368 0 : return;
369 : }
370 :
371 0 : if (aSource.IsEmpty()) {
372 0 : return;
373 : }
374 :
375 0 : MarkChanged();
376 :
377 0 : SkRect destRect = RectToSkRect(aDest);
378 0 : SkRect sourceRect = RectToSkRect(aSource);
379 :
380 : SkMatrix matrix;
381 0 : matrix.setRectToRect(sourceRect, destRect, SkMatrix::kFill_ScaleToFit);
382 :
383 0 : const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
384 :
385 0 : AutoPaintSetup paint(mCanvas.get(), aOptions);
386 0 : SkShader *shader = SkShader::CreateBitmapShader(bitmap, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
387 0 : shader->setLocalMatrix(matrix);
388 0 : SkSafeUnref(paint.mPaint.setShader(shader));
389 0 : if (aSurfOptions.mFilter != FILTER_LINEAR) {
390 0 : paint.mPaint.setFilterBitmap(false);
391 : }
392 0 : mCanvas->drawRect(destRect, paint.mPaint);
393 : }
394 :
395 : void
396 0 : DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface,
397 : const Point &aDest,
398 : const Color &aColor,
399 : const Point &aOffset,
400 : Float aSigma,
401 : CompositionOp aOperator)
402 : {
403 0 : MarkChanged();
404 0 : mCanvas->save(SkCanvas::kMatrix_SaveFlag);
405 0 : mCanvas->resetMatrix();
406 :
407 : uint32_t blurFlags = SkBlurMaskFilter::kHighQuality_BlurFlag |
408 0 : SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
409 0 : const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
410 0 : SkShader* shader = SkShader::CreateBitmapShader(bitmap, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
411 : SkMatrix matrix;
412 0 : matrix.reset();
413 0 : matrix.setTranslateX(SkFloatToScalar(aDest.x));
414 0 : matrix.setTranslateY(SkFloatToScalar(aDest.y));
415 0 : shader->setLocalMatrix(matrix);
416 0 : SkLayerDrawLooper* dl = new SkLayerDrawLooper;
417 0 : SkLayerDrawLooper::LayerInfo info;
418 0 : info.fPaintBits |= SkLayerDrawLooper::kShader_Bit;
419 0 : SkPaint *layerPaint = dl->addLayer(info);
420 0 : layerPaint->setShader(shader);
421 :
422 0 : info.fPaintBits = 0;
423 0 : info.fPaintBits |= SkLayerDrawLooper::kMaskFilter_Bit;
424 0 : info.fPaintBits |= SkLayerDrawLooper::kColorFilter_Bit;
425 0 : info.fColorMode = SkXfermode::kDst_Mode;
426 0 : info.fOffset.set(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y));
427 0 : info.fPostTranslate = true;
428 :
429 0 : SkMaskFilter* mf = SkBlurMaskFilter::Create(aSigma, SkBlurMaskFilter::kNormal_BlurStyle, blurFlags);
430 0 : SkColor color = ColorToSkColor(aColor, 1);
431 0 : SkColorFilter* cf = SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcIn_Mode);
432 :
433 :
434 0 : layerPaint = dl->addLayer(info);
435 0 : SkSafeUnref(layerPaint->setMaskFilter(mf));
436 0 : SkSafeUnref(layerPaint->setColorFilter(cf));
437 0 : layerPaint->setColor(color);
438 :
439 : // TODO: This is using the rasterizer to calculate an alpha mask
440 : // on both the shadow and normal layers. We should fix this
441 : // properly so it only happens for the shadow layer
442 0 : SkLayerRasterizer *raster = new SkLayerRasterizer();
443 0 : SkPaint maskPaint;
444 0 : SkSafeUnref(maskPaint.setShader(shader));
445 0 : raster->addLayer(maskPaint, 0, 0);
446 :
447 0 : SkPaint paint;
448 0 : paint.setAntiAlias(true);
449 0 : SkSafeUnref(paint.setRasterizer(raster));
450 0 : paint.setXfermodeMode(GfxOpToSkiaOp(aOperator));
451 0 : SkSafeUnref(paint.setLooper(dl));
452 :
453 0 : SkRect rect = RectToSkRect(Rect(aDest.x, aDest.y, bitmap.width(), bitmap.height()));
454 0 : mCanvas->drawRect(rect, paint);
455 0 : mCanvas->restore();
456 0 : }
457 :
458 : void
459 0 : DrawTargetSkia::FillRect(const Rect &aRect,
460 : const Pattern &aPattern,
461 : const DrawOptions &aOptions)
462 : {
463 0 : MarkChanged();
464 0 : SkRect rect = RectToSkRect(aRect);
465 0 : AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
466 :
467 0 : mCanvas->drawRect(rect, paint.mPaint);
468 0 : }
469 :
470 : void
471 0 : DrawTargetSkia::Stroke(const Path *aPath,
472 : const Pattern &aPattern,
473 : const StrokeOptions &aStrokeOptions,
474 : const DrawOptions &aOptions)
475 : {
476 0 : MarkChanged();
477 0 : if (aPath->GetBackendType() != BACKEND_SKIA) {
478 0 : return;
479 : }
480 :
481 0 : const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
482 :
483 :
484 0 : AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
485 0 : if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
486 : return;
487 : }
488 :
489 0 : mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint);
490 : }
491 :
492 : void
493 0 : DrawTargetSkia::StrokeRect(const Rect &aRect,
494 : const Pattern &aPattern,
495 : const StrokeOptions &aStrokeOptions,
496 : const DrawOptions &aOptions)
497 : {
498 0 : MarkChanged();
499 0 : AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
500 0 : if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
501 : return;
502 : }
503 :
504 0 : mCanvas->drawRect(RectToSkRect(aRect), paint.mPaint);
505 : }
506 :
507 : void
508 0 : DrawTargetSkia::StrokeLine(const Point &aStart,
509 : const Point &aEnd,
510 : const Pattern &aPattern,
511 : const StrokeOptions &aStrokeOptions,
512 : const DrawOptions &aOptions)
513 : {
514 0 : MarkChanged();
515 0 : AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
516 0 : if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
517 : return;
518 : }
519 :
520 : mCanvas->drawLine(SkFloatToScalar(aStart.x), SkFloatToScalar(aStart.y),
521 : SkFloatToScalar(aEnd.x), SkFloatToScalar(aEnd.y),
522 0 : paint.mPaint);
523 : }
524 :
525 : void
526 0 : DrawTargetSkia::Fill(const Path *aPath,
527 : const Pattern &aPattern,
528 : const DrawOptions &aOptions)
529 : {
530 0 : MarkChanged();
531 0 : if (aPath->GetBackendType() != BACKEND_SKIA) {
532 0 : return;
533 : }
534 :
535 0 : const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
536 :
537 0 : AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
538 :
539 0 : mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint);
540 : }
541 :
542 : void
543 0 : DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
544 : const GlyphBuffer &aBuffer,
545 : const Pattern &aPattern,
546 : const DrawOptions &aOptions)
547 : {
548 0 : if (aFont->GetType() != FONT_MAC && aFont->GetType() != FONT_SKIA) {
549 0 : return;
550 : }
551 :
552 0 : MarkChanged();
553 :
554 0 : ScaledFontBase* skiaFont = static_cast<ScaledFontBase*>(aFont);
555 :
556 0 : AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
557 0 : paint.mPaint.setTypeface(skiaFont->GetSkTypeface());
558 0 : paint.mPaint.setTextSize(SkFloatToScalar(skiaFont->mSize));
559 0 : paint.mPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
560 :
561 0 : std::vector<uint16_t> indices;
562 0 : std::vector<SkPoint> offsets;
563 0 : indices.resize(aBuffer.mNumGlyphs);
564 0 : offsets.resize(aBuffer.mNumGlyphs);
565 :
566 0 : for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) {
567 0 : indices[i] = aBuffer.mGlyphs[i].mIndex;
568 0 : offsets[i].fX = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.x);
569 0 : offsets[i].fY = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.y);
570 : }
571 :
572 0 : mCanvas->drawPosText(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), paint.mPaint);
573 : }
574 :
575 : void
576 0 : DrawTargetSkia::Mask(const Pattern &aSource,
577 : const Pattern &aMask,
578 : const DrawOptions &aOptions)
579 : {
580 0 : MarkChanged();
581 0 : AutoPaintSetup paint(mCanvas.get(), aOptions, aSource);
582 :
583 0 : SkPaint maskPaint;
584 0 : SetPaintPattern(maskPaint, aMask);
585 :
586 0 : SkLayerRasterizer *raster = new SkLayerRasterizer();
587 0 : raster->addLayer(maskPaint);
588 0 : SkSafeUnref(paint.mPaint.setRasterizer(raster));
589 :
590 : // Skia only uses the mask rasterizer when we are drawing a path/rect.
591 : // Take our destination bounds and convert them into user space to use
592 : // as the path to draw.
593 0 : SkPath path;
594 0 : path.addRect(SkRect::MakeWH(mSize.width, mSize.height));
595 :
596 0 : Matrix temp = mTransform;
597 0 : temp.Invert();
598 : SkMatrix mat;
599 0 : GfxMatrixToSkiaMatrix(temp, mat);
600 0 : path.transform(mat);
601 :
602 0 : mCanvas->drawPath(path, paint.mPaint);
603 0 : }
604 :
605 : TemporaryRef<SourceSurface>
606 0 : DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData,
607 : const IntSize &aSize,
608 : int32_t aStride,
609 : SurfaceFormat aFormat) const
610 : {
611 0 : RefPtr<SourceSurfaceSkia> newSurf = new SourceSurfaceSkia();
612 :
613 0 : if (!newSurf->InitFromData(aData, aSize, aStride, aFormat)) {
614 0 : gfxDebug() << *this << ": Failure to create source surface from data. Size: " << aSize;
615 0 : return NULL;
616 : }
617 :
618 0 : return newSurf;
619 : }
620 :
621 : TemporaryRef<DrawTarget>
622 0 : DrawTargetSkia::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
623 : {
624 0 : RefPtr<DrawTargetSkia> target = new DrawTargetSkia();
625 0 : if (!target->Init(aSize, aFormat)) {
626 0 : return NULL;
627 : }
628 0 : return target;
629 : }
630 :
631 : TemporaryRef<SourceSurface>
632 0 : DrawTargetSkia::OptimizeSourceSurface(SourceSurface *aSurface) const
633 : {
634 0 : return NULL;
635 : }
636 :
637 : TemporaryRef<SourceSurface>
638 0 : DrawTargetSkia::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
639 : {
640 0 : return NULL;
641 : }
642 :
643 : void
644 0 : DrawTargetSkia::CopySurface(SourceSurface *aSurface,
645 : const IntRect& aSourceRect,
646 : const IntPoint &aDestination)
647 : {
648 : //TODO: We could just use writePixels() here if the sourceRect is the entire source
649 :
650 0 : if (aSurface->GetType() != SURFACE_SKIA) {
651 0 : return;
652 : }
653 :
654 0 : MarkChanged();
655 :
656 0 : const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
657 :
658 0 : mCanvas->save();
659 0 : mCanvas->resetMatrix();
660 0 : SkRect dest = IntRectToSkRect(IntRect(aDestination.x, aDestination.y, aSourceRect.width, aSourceRect.height));
661 0 : SkIRect source = IntRectToSkIRect(aSourceRect);
662 0 : mCanvas->clipRect(dest, SkRegion::kReplace_Op);
663 0 : SkPaint paint;
664 0 : paint.setXfermodeMode(GfxOpToSkiaOp(OP_SOURCE));
665 0 : mCanvas->drawBitmapRect(bitmap, &source, dest, &paint);
666 0 : mCanvas->restore();
667 : }
668 :
669 : bool
670 0 : DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat)
671 : {
672 0 : mBitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height);
673 0 : if (!mBitmap.allocPixels()) {
674 0 : return false;
675 : }
676 0 : mBitmap.eraseARGB(0, 0, 0, 0);
677 0 : SkAutoTUnref<SkDevice> device(new SkDevice(mBitmap));
678 0 : SkAutoTUnref<SkCanvas> canvas(new SkCanvas(device.get()));
679 0 : mSize = aSize;
680 :
681 0 : mDevice = device.get();
682 0 : mCanvas = canvas.get();
683 0 : mFormat = aFormat;
684 0 : return true;
685 : }
686 :
687 : void
688 0 : DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat)
689 : {
690 0 : mBitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height, aStride);
691 0 : mBitmap.setPixels(aData);
692 :
693 0 : SkAutoTUnref<SkDevice> device(new SkDevice(mBitmap));
694 0 : SkAutoTUnref<SkCanvas> canvas(new SkCanvas(device.get()));
695 0 : mSize = aSize;
696 :
697 0 : mDevice = device.get();
698 0 : mCanvas = canvas.get();
699 0 : mFormat = aFormat;
700 0 : }
701 :
702 : void
703 0 : DrawTargetSkia::SetTransform(const Matrix& aTransform)
704 : {
705 : SkMatrix mat;
706 0 : GfxMatrixToSkiaMatrix(aTransform, mat);
707 0 : mCanvas->setMatrix(mat);
708 0 : mTransform = aTransform;
709 0 : }
710 :
711 : TemporaryRef<PathBuilder>
712 0 : DrawTargetSkia::CreatePathBuilder(FillRule aFillRule) const
713 : {
714 0 : RefPtr<PathBuilderSkia> pb = new PathBuilderSkia(aFillRule);
715 0 : return pb;
716 : }
717 :
718 : void
719 0 : DrawTargetSkia::ClearRect(const Rect &aRect)
720 : {
721 0 : MarkChanged();
722 0 : SkPaint paint;
723 0 : mCanvas->save();
724 0 : mCanvas->clipRect(RectToSkRect(aRect), SkRegion::kIntersect_Op, USE_SOFT_CLIPPING);
725 0 : paint.setColor(SkColorSetARGB(0, 0, 0, 0));
726 0 : paint.setXfermodeMode(SkXfermode::kSrc_Mode);
727 0 : mCanvas->drawPaint(paint);
728 0 : mCanvas->restore();
729 0 : }
730 :
731 : void
732 0 : DrawTargetSkia::PushClip(const Path *aPath)
733 : {
734 0 : if (aPath->GetBackendType() != BACKEND_SKIA) {
735 0 : return;
736 : }
737 :
738 0 : const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
739 0 : mCanvas->save(SkCanvas::kClip_SaveFlag);
740 0 : mCanvas->clipPath(skiaPath->GetPath(), SkRegion::kIntersect_Op, USE_SOFT_CLIPPING);
741 : }
742 :
743 : void
744 0 : DrawTargetSkia::PushClipRect(const Rect& aRect)
745 : {
746 0 : SkRect rect = RectToSkRect(aRect);
747 :
748 0 : mCanvas->save(SkCanvas::kClip_SaveFlag);
749 0 : mCanvas->clipRect(rect, SkRegion::kIntersect_Op, USE_SOFT_CLIPPING);
750 0 : }
751 :
752 : void
753 0 : DrawTargetSkia::PopClip()
754 : {
755 0 : mCanvas->restore();
756 0 : }
757 :
758 : TemporaryRef<GradientStops>
759 0 : DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const
760 : {
761 0 : std::vector<GradientStop> stops;
762 0 : stops.resize(aNumStops);
763 0 : for (uint32_t i = 0; i < aNumStops; i++) {
764 0 : stops[i] = aStops[i];
765 : }
766 0 : std::stable_sort(stops.begin(), stops.end());
767 :
768 0 : return new GradientStopsSkia(stops, aNumStops, aExtendMode);
769 : }
770 :
771 : void
772 0 : DrawTargetSkia::AppendSnapshot(SourceSurfaceSkia* aSnapshot)
773 : {
774 0 : mSnapshots.push_back(aSnapshot);
775 0 : }
776 :
777 : void
778 0 : DrawTargetSkia::RemoveSnapshot(SourceSurfaceSkia* aSnapshot)
779 : {
780 0 : std::vector<SourceSurfaceSkia*>::iterator iter = std::find(mSnapshots.begin(), mSnapshots.end(), aSnapshot);
781 0 : if (iter != mSnapshots.end()) {
782 0 : mSnapshots.erase(iter);
783 : }
784 0 : }
785 :
786 : void
787 0 : DrawTargetSkia::MarkChanged()
788 : {
789 0 : if (mSnapshots.size()) {
790 0 : for (std::vector<SourceSurfaceSkia*>::iterator iter = mSnapshots.begin();
791 0 : iter != mSnapshots.end(); iter++) {
792 0 : (*iter)->DrawTargetWillChange();
793 : }
794 : // All snapshots will now have copied data.
795 0 : mSnapshots.clear();
796 : }
797 0 : }
798 :
799 : }
800 : }
|