11db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger/*
21db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * Copyright (C) 2015 The Android Open Source Project
31db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger *
41db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * Licensed under the Apache License, Version 2.0 (the "License");
51db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * you may not use this file except in compliance with the License.
61db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * You may obtain a copy of the License at
71db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger *
81db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger *      http://www.apache.org/licenses/LICENSE-2.0
91db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger *
101db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * Unless required by applicable law or agreed to in writing, software
111db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * distributed under the License is distributed on an "AS IS" BASIS,
121db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * See the License for the specific language governing permissions and
141db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * limitations under the License.
151db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger */
161db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
171db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger#include "SkiaCanvasProxy.h"
181db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
1952eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include <memory>
2052eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn
2152eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include <log/log.h>
22aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv
23db15537e6e0d35c7ed3b1bef45e421760be70683Mark Salyzyn#include "hwui/Bitmap.h"
24770e0b500793bce45442b5f403913d14017df4e8Stan Iliev#include <SkLatticeIter.h>
251db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger#include <SkPatchUtils.h>
26a11ee3c4131d889d57b7d2cf30faa7c105b23b10Ben Wagner#include <SkPaint.h>
27a11ee3c4131d889d57b7d2cf30faa7c105b23b10Ben Wagner#include <SkPath.h>
2817c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson#include <SkPixelRef.h>
29a11ee3c4131d889d57b7d2cf30faa7c105b23b10Ben Wagner#include <SkRect.h>
30a11ee3c4131d889d57b7d2cf30faa7c105b23b10Ben Wagner#include <SkRRect.h>
31afc221499d943386256feb9db46c119ff834bf79Yuqian Li#include <SkRSXform.h>
3279fc3b1f1675364dbb739ffa511a68ed5a80f357Matt Sarett#include <SkSurface.h>
3309bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger#include <SkTextBlobRunIterator.h>
34871cd2dd6074544bd41a84ff38255d81a392546aMike Reed#include <SkVertices.h>
351db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
361db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergernamespace android {
371db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergernamespace uirenderer {
381db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
39b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom HudsonSkiaCanvasProxy::SkiaCanvasProxy(Canvas* canvas, bool filterHwuiCalls)
401db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        : INHERITED(canvas->width(), canvas->height())
41b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson        , mCanvas(canvas)
42b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson        , mFilterHwuiCalls(filterHwuiCalls) {}
431db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
441db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawPaint(const SkPaint& paint) {
451db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->drawPaint(paint);
461db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
471db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
481db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawPoints(PointMode pointMode, size_t count, const SkPoint pts[],
491db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        const SkPaint& paint) {
50b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    if (!pts || count == 0) {
51b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson        return;
52b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    }
53b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson
541db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // convert the SkPoints into floats
55e3a40ea488c7cfa396d5901255719a6ddab791d4Ben Wagner    static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
561db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    const size_t floatCount = count << 1;
571db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    const float* floatArray = &pts[0].fX;
581db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
591db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    switch (pointMode) {
601db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        case kPoints_PointMode: {
611db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            mCanvas->drawPoints(floatArray, floatCount, paint);
621db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            break;
631db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
641db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        case kLines_PointMode: {
651db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            mCanvas->drawLines(floatArray, floatCount, paint);
661db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            break;
671db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
681db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        case kPolygon_PointMode: {
691db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            SkPaint strokedPaint(paint);
701db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            strokedPaint.setStyle(SkPaint::kStroke_Style);
711db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
721db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            SkPath path;
731db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            for (size_t i = 0; i < count - 1; i++) {
741db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger                path.moveTo(pts[i]);
751db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger                path.lineTo(pts[i+1]);
761db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger                this->drawPath(path, strokedPaint);
771db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger                path.rewind();
781db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            }
791db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            break;
801db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
811db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        default:
821db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            LOG_ALWAYS_FATAL("Unknown point type");
831db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
841db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
851db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
861db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawOval(const SkRect& rect, const SkPaint& paint) {
871db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->drawOval(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, paint);
881db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
891db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
901db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawRect(const SkRect& rect, const SkPaint& paint) {
911db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->drawRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, paint);
921db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
931db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
941db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawRRect(const SkRRect& roundRect, const SkPaint& paint) {
951db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    if (!roundRect.isComplex()) {
961db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        const SkRect& rect = roundRect.rect();
971db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        SkVector radii = roundRect.getSimpleRadii();
981db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        mCanvas->drawRoundRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
991db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger                               radii.fX, radii.fY, paint);
1001db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    } else {
1011db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        SkPath path;
1021db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        path.addRRect(roundRect);
1031db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        mCanvas->drawPath(path, paint);
1041db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
1051db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
1061db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
1079969111d9c8017cdd439edbb2c54ef9678b24a59Yuqian Livoid SkiaCanvasProxy::onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
1089969111d9c8017cdd439edbb2c54ef9678b24a59Yuqian Li                                bool useCenter, const SkPaint& paint) {
1099969111d9c8017cdd439edbb2c54ef9678b24a59Yuqian Li    mCanvas->drawArc(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
1109969111d9c8017cdd439edbb2c54ef9678b24a59Yuqian Li                     startAngle, sweepAngle, useCenter, paint);
1119969111d9c8017cdd439edbb2c54ef9678b24a59Yuqian Li}
1129969111d9c8017cdd439edbb2c54ef9678b24a59Yuqian Li
1131db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawPath(const SkPath& path, const SkPaint& paint) {
1141db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->drawPath(path, paint);
1151db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
1161db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
1171db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
1181db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        const SkPaint* paint) {
119fc9999505a36c66892d7ccce85187936105f4f36sergeyv    sk_sp<Bitmap> hwuiBitmap = Bitmap::createFrom(bitmap.info(), *bitmap.pixelRef());
12017c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson    // HWUI doesn't support extractSubset(), so convert any subsetted bitmap into
12117c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson    // a drawBitmapRect(); pass through an un-subsetted bitmap.
122fc9999505a36c66892d7ccce85187936105f4f36sergeyv    if (hwuiBitmap && bitmap.dimensions() != hwuiBitmap->info().dimensions()) {
12317c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson        SkIPoint origin = bitmap.pixelRefOrigin();
124fc9999505a36c66892d7ccce85187936105f4f36sergeyv        mCanvas->drawBitmap(*hwuiBitmap, origin.fX, origin.fY,
12517c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson                            origin.fX + bitmap.dimensions().width(),
12617c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson                            origin.fY + bitmap.dimensions().height(),
12717c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson                            left, top,
12817c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson                            left + bitmap.dimensions().width(),
12917c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson                            top + bitmap.dimensions().height(),
13017c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson                            paint);
13117c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson    } else {
132aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        mCanvas->drawBitmap(*hwuiBitmap, left, top, paint);
13317c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson    }
1341db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
1351db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
136fc9999505a36c66892d7ccce85187936105f4f36sergeyvvoid SkiaCanvasProxy::onDrawBitmapRect(const SkBitmap& skBitmap, const SkRect* srcPtr,
137f35b989d26bb98900f6c5fa2e586326b30b6e161Leon Scroggins III        const SkRect& dst, const SkPaint* paint, SrcRectConstraint) {
138fc9999505a36c66892d7ccce85187936105f4f36sergeyv    SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(skBitmap.width(), skBitmap.height());
13917c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson    // TODO: if bitmap is a subset, do we need to add pixelRefOrigin to src?
140fc9999505a36c66892d7ccce85187936105f4f36sergeyv   Bitmap* bitmap = reinterpret_cast<Bitmap*>(skBitmap.pixelRef());
141fc9999505a36c66892d7ccce85187936105f4f36sergeyv   mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
1421db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger                        dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
1431db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
1441db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
1451db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
1461db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        const SkRect& dst, const SkPaint*) {
1471db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    //TODO make nine-patch drawing a method on Canvas.h
1481db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkDEBUGFAIL("SkiaCanvasProxy::onDrawBitmapNine is not yet supported");
1491db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
1501db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
151770e0b500793bce45442b5f403913d14017df4e8Stan Ilievvoid SkiaCanvasProxy::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
152770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        const SkPaint* paint) {
153770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    SkBitmap skiaBitmap;
154770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    if (image->asLegacyBitmap(&skiaBitmap, SkImage::kRO_LegacyBitmapMode)) {
155770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        onDrawBitmap(skiaBitmap, left, top, paint);
156770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    }
157770e0b500793bce45442b5f403913d14017df4e8Stan Iliev}
158770e0b500793bce45442b5f403913d14017df4e8Stan Iliev
159770e0b500793bce45442b5f403913d14017df4e8Stan Ilievvoid SkiaCanvasProxy::onDrawImageRect(const SkImage* image, const SkRect* srcPtr, const SkRect& dst,
160770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        const SkPaint* paint, SrcRectConstraint constraint) {
161770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    SkBitmap skiaBitmap;
162770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    if (image->asLegacyBitmap(&skiaBitmap, SkImage::kRO_LegacyBitmapMode)) {
163770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        sk_sp<Bitmap> bitmap = Bitmap::createFrom(skiaBitmap.info(), *skiaBitmap.pixelRef());
164770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(image->width(), image->height());
165770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
166770e0b500793bce45442b5f403913d14017df4e8Stan Iliev                dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
167770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    }
168770e0b500793bce45442b5f403913d14017df4e8Stan Iliev}
169770e0b500793bce45442b5f403913d14017df4e8Stan Iliev
170770e0b500793bce45442b5f403913d14017df4e8Stan Ilievvoid SkiaCanvasProxy::onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
171770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        const SkPaint*) {
172770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    SkDEBUGFAIL("SkiaCanvasProxy::onDrawImageNine is not yet supported");
173770e0b500793bce45442b5f403913d14017df4e8Stan Iliev}
174770e0b500793bce45442b5f403913d14017df4e8Stan Iliev
175770e0b500793bce45442b5f403913d14017df4e8Stan Ilievvoid SkiaCanvasProxy::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
176770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        const SkRect& dst, const SkPaint* paint) {
177770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    SkLatticeIter iter(lattice, dst);
178770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    SkRect srcR, dstR;
179770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    while (iter.next(&srcR, &dstR)) {
180770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        onDrawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
181770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    }
182770e0b500793bce45442b5f403913d14017df4e8Stan Iliev}
183770e0b500793bce45442b5f403913d14017df4e8Stan Iliev
184871cd2dd6074544bd41a84ff38255d81a392546aMike Reedvoid SkiaCanvasProxy::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
185871cd2dd6074544bd41a84ff38255d81a392546aMike Reed        const SkPaint& paint) {
186c2f31df8b3b9a237e9abffc59c61804ad8495073Mike Reed    // TODO: should we pass through blendmode
187b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    if (mFilterHwuiCalls) {
188b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson        return;
189b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    }
1901db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // convert the SkPoints into floats
191e3a40ea488c7cfa396d5901255719a6ddab791d4Ben Wagner    static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
192871cd2dd6074544bd41a84ff38255d81a392546aMike Reed    const int floatCount = vertices->vertexCount() << 1;
193871cd2dd6074544bd41a84ff38255d81a392546aMike Reed    const float* vArray = (const float*)vertices->positions();
194871cd2dd6074544bd41a84ff38255d81a392546aMike Reed    const float* tArray = (const float*)vertices->texCoords();
195871cd2dd6074544bd41a84ff38255d81a392546aMike Reed    const int* cArray = (const int*)vertices->colors();
196871cd2dd6074544bd41a84ff38255d81a392546aMike Reed    mCanvas->drawVertices(vertices->mode(), floatCount, vArray, tArray, cArray,
197871cd2dd6074544bd41a84ff38255d81a392546aMike Reed            vertices->indices(), vertices->indexCount(), paint);
1981db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
1991db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
20079fc3b1f1675364dbb739ffa511a68ed5a80f357Matt Sarettsk_sp<SkSurface> SkiaCanvasProxy::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
2011db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkDEBUGFAIL("SkiaCanvasProxy::onNewSurface is not supported");
2021db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    return NULL;
2031db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2041db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2051db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::willSave() {
206eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    mCanvas->save(android::SaveFlags::MatrixClip);
207eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita}
208eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita
209eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malitastatic inline SaveFlags::Flags saveFlags(SkCanvas::SaveLayerFlags layerFlags) {
210eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    SaveFlags::Flags saveFlags = 0;
211eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita
212eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    if (!(layerFlags & SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag)) {
213eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        saveFlags |= SaveFlags::ClipToLayer;
214eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    }
215eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita
216eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    if (!(layerFlags & SkCanvas::kIsOpaque_SaveLayerFlag)) {
217eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        saveFlags |= SaveFlags::HasAlphaLayer;
218eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    }
219eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita
220eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    return saveFlags;
2211db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2221db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2235518e7cbd4e8d7a7cb3d60a4251eccc3b7fb82dbLeon Scroggins IIISkCanvas::SaveLayerStrategy SkiaCanvasProxy::getSaveLayerStrategy(const SaveLayerRec& saveLayerRec) {
2241db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkRect rect;
2255518e7cbd4e8d7a7cb3d60a4251eccc3b7fb82dbLeon Scroggins III    if (saveLayerRec.fBounds) {
2265518e7cbd4e8d7a7cb3d60a4251eccc3b7fb82dbLeon Scroggins III        rect = *saveLayerRec.fBounds;
2275518e7cbd4e8d7a7cb3d60a4251eccc3b7fb82dbLeon Scroggins III    } else if (!mCanvas->getClipBounds(&rect)) {
2281db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        rect = SkRect::MakeEmpty();
2291db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
2305518e7cbd4e8d7a7cb3d60a4251eccc3b7fb82dbLeon Scroggins III    mCanvas->saveLayer(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, saveLayerRec.fPaint,
231eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita                       saveFlags(saveLayerRec.fSaveLayerFlags));
2321db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    return SkCanvas::kNoLayer_SaveLayerStrategy;
2331db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2341db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2351db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::willRestore() {
2361db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->restore();
2371db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2381db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2391db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::didConcat(const SkMatrix& matrix) {
2401db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->concat(matrix);
2411db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2421db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2431db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::didSetMatrix(const SkMatrix& matrix) {
2446daa13c5fa7577fa1d8371deca446f6ca911f38fChris Craik    mCanvas->setMatrix(matrix);
2451db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2461db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2471db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2481db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        const SkPaint& paint) {
2491db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkPath path;
2501db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    path.addRRect(outer);
2511db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    path.addRRect(inner);
2521db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    path.setFillType(SkPath::kEvenOdd_FillType);
2531db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    this->drawPath(path, paint);
2541db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2551db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2561db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger/**
2571db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * Utility class that converts the incoming text & paint from the given encoding
2581db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * into glyphIDs.
2591db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger */
2601db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergerclass GlyphIDConverter {
2611db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergerpublic:
2621db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    GlyphIDConverter(const void* text, size_t byteLength, const SkPaint& origPaint) {
2631db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        paint = origPaint;
2641db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        if (paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding) {
2651db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            glyphIDs = (uint16_t*)text;
2661db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            count = byteLength >> 1;
2671db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        } else {
2686bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner             // ensure space for one glyph per ID given UTF8 encoding.
2696bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner            storage.reset(new uint16_t[byteLength]);
2701db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            glyphIDs = storage.get();
2711db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            count = paint.textToGlyphs(text, byteLength, storage.get());
2721db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
2731db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
2741db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
2751db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2761db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkPaint paint;
2771db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    uint16_t* glyphIDs;
2781db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    int count;
2791db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergerprivate:
2806bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner    std::unique_ptr<uint16_t[]> storage;
2811db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger};
2821db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2831db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2841db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        const SkPaint& origPaint) {
2851db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // convert to glyphIDs if necessary
2861db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    GlyphIDConverter glyphs(text, byteLength, origPaint);
2871db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2881db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // compute the glyph positions
2896bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner    std::unique_ptr<SkPoint[]> pointStorage(new SkPoint[glyphs.count]);
2906bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner    std::unique_ptr<SkScalar[]> glyphWidths(new SkScalar[glyphs.count]);
2911db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    glyphs.paint.getTextWidths(glyphs.glyphIDs, glyphs.count << 1, glyphWidths.get());
2921db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2931db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // compute conservative bounds
2941db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // NOTE: We could call the faster paint.getFontBounds for a less accurate,
2951db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    //       but even more conservative bounds if this  is too slow.
2961db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkRect bounds;
2971db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    glyphs.paint.measureText(glyphs.glyphIDs, glyphs.count << 1, &bounds);
2981db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2991db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // adjust for non-left alignment
3001db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    if (glyphs.paint.getTextAlign() != SkPaint::kLeft_Align) {
3011db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        SkScalar stop = 0;
3021db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        for (int i = 0; i < glyphs.count; i++) {
3031db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            stop += glyphWidths[i];
3041db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
3051db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        if (glyphs.paint.getTextAlign() == SkPaint::kCenter_Align) {
3061db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            stop = SkScalarHalf(stop);
3071db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
3081db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        if (glyphs.paint.isVerticalText()) {
3091db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            y -= stop;
3101db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        } else {
3111db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            x -= stop;
3121db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
3131db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
3141db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3151db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // setup the first glyph position and adjust bounds if needed
316806a6f07a37c16b37631d8707dd1f2b41276fafcTom Hudson    int xBaseline = 0;
317806a6f07a37c16b37631d8707dd1f2b41276fafcTom Hudson    int yBaseline = 0;
3181db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    if (mCanvas->drawTextAbsolutePos()) {
3191db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        bounds.offset(x,y);
320806a6f07a37c16b37631d8707dd1f2b41276fafcTom Hudson        xBaseline = x;
321806a6f07a37c16b37631d8707dd1f2b41276fafcTom Hudson        yBaseline = y;
3221db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
323806a6f07a37c16b37631d8707dd1f2b41276fafcTom Hudson    pointStorage[0].set(xBaseline, yBaseline);
3241db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3251db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // setup the remaining glyph positions
3261db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    if (glyphs.paint.isVerticalText()) {
3271db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        for (int i = 1; i < glyphs.count; i++) {
328806a6f07a37c16b37631d8707dd1f2b41276fafcTom Hudson            pointStorage[i].set(xBaseline, glyphWidths[i-1] + pointStorage[i-1].fY);
3291db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
3301db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    } else {
3311db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        for (int i = 1; i < glyphs.count; i++) {
332806a6f07a37c16b37631d8707dd1f2b41276fafcTom Hudson            pointStorage[i].set(glyphWidths[i-1] + pointStorage[i-1].fX, yBaseline);
3331db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
3341db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
3351db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
336e3a40ea488c7cfa396d5901255719a6ddab791d4Ben Wagner    static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
337dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    mCanvas->drawGlyphs(glyphs.glyphIDs, &pointStorage[0].fX, glyphs.count, glyphs.paint,
3381db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger                      x, y, bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
3391db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
3401db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3411db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
3421db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        const SkPaint& origPaint) {
3431db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // convert to glyphIDs if necessary
3441db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    GlyphIDConverter glyphs(text, byteLength, origPaint);
3451db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3461db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // convert to relative positions if necessary
3471db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    int x, y;
3481db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    const SkPoint* posArray;
3496bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner    std::unique_ptr<SkPoint[]> pointStorage;
3501db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    if (mCanvas->drawTextAbsolutePos()) {
3511db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        x = 0;
3521db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        y = 0;
3531db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        posArray = pos;
3541db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    } else {
3551db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        x = pos[0].fX;
3561db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        y = pos[0].fY;
3576bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner        pointStorage.reset(new SkPoint[glyphs.count]);
3581db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        for (int i = 0; i < glyphs.count; i++) {
3596bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner            pointStorage[i].fX = pos[i].fX - x;
3606bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner            pointStorage[i].fY = pos[i].fY - y;
3611db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
3626bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner        posArray = pointStorage.get();
3631db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
3641db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
36535934cccabf72879603ef37222da2195445f027eDerek Sollenberger    // Compute conservative bounds.  If the content has already been processed
36635934cccabf72879603ef37222da2195445f027eDerek Sollenberger    // by Minikin then it had already computed these bounds.  Unfortunately,
36735934cccabf72879603ef37222da2195445f027eDerek Sollenberger    // there is no way to capture those bounds as part of the Skia drawPosText
36835934cccabf72879603ef37222da2195445f027eDerek Sollenberger    // API so we need to do that computation again here.
369d84d2ee3359af8478afd3f891d5d316af1a562edStan Iliev    SkRect bounds = SkRect::MakeEmpty();
37035934cccabf72879603ef37222da2195445f027eDerek Sollenberger    for (int i = 0; i < glyphs.count; i++) {
371d84d2ee3359af8478afd3f891d5d316af1a562edStan Iliev        SkRect glyphBounds = SkRect::MakeEmpty();
37235934cccabf72879603ef37222da2195445f027eDerek Sollenberger        glyphs.paint.measureText(&glyphs.glyphIDs[i], sizeof(uint16_t), &glyphBounds);
37335934cccabf72879603ef37222da2195445f027eDerek Sollenberger        glyphBounds.offset(pos[i].fX, pos[i].fY);
37435934cccabf72879603ef37222da2195445f027eDerek Sollenberger        bounds.join(glyphBounds);
37535934cccabf72879603ef37222da2195445f027eDerek Sollenberger    }
3761db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
377e3a40ea488c7cfa396d5901255719a6ddab791d4Ben Wagner    static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
378dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    mCanvas->drawGlyphs(glyphs.glyphIDs, &posArray[0].fX, glyphs.count, glyphs.paint, x, y,
3791db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger                      bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
3801db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
3811db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3821db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
3831db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        SkScalar constY, const SkPaint& paint) {
3841db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    const size_t pointCount = byteLength >> 1;
3856bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner    std::unique_ptr<SkPoint[]> pts(new SkPoint[pointCount]);
3861db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    for (size_t i = 0; i < pointCount; i++) {
3871db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        pts[i].set(xpos[i], constY);
3881db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
3896bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner    this->onDrawPosText(text, byteLength, pts.get(), paint);
3901db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
3911db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3921db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
3931db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        const SkMatrix* matrix, const SkPaint& origPaint) {
394afc221499d943386256feb9db46c119ff834bf79Yuqian Li    SkDEBUGFAIL("SkiaCanvasProxy::onDrawTextOnPath is not supported");
3951db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
3961db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
397afc221499d943386256feb9db46c119ff834bf79Yuqian Livoid SkiaCanvasProxy::onDrawTextRSXform(const void* text, size_t byteLength,
398afc221499d943386256feb9db46c119ff834bf79Yuqian Li        const SkRSXform xform[], const SkRect* cullRect, const SkPaint& paint) {
399afc221499d943386256feb9db46c119ff834bf79Yuqian Li    GlyphIDConverter glyphs(text, byteLength, paint); // Just get count
400afc221499d943386256feb9db46c119ff834bf79Yuqian Li    SkMatrix localM, currM, origM;
401afc221499d943386256feb9db46c119ff834bf79Yuqian Li    mCanvas->getMatrix(&currM);
402afc221499d943386256feb9db46c119ff834bf79Yuqian Li    origM = currM;
403afc221499d943386256feb9db46c119ff834bf79Yuqian Li    for (int i = 0; i < glyphs.count; i++) {
404afc221499d943386256feb9db46c119ff834bf79Yuqian Li        localM.setRSXform(*xform++);
405afc221499d943386256feb9db46c119ff834bf79Yuqian Li        currM.setConcat(origM, localM);
406afc221499d943386256feb9db46c119ff834bf79Yuqian Li        mCanvas->setMatrix(currM);
407afc221499d943386256feb9db46c119ff834bf79Yuqian Li        this->onDrawText((char*)text + (byteLength / glyphs.count * i),
408afc221499d943386256feb9db46c119ff834bf79Yuqian Li                         byteLength / glyphs.count, 0, 0, paint);
409afc221499d943386256feb9db46c119ff834bf79Yuqian Li    }
410afc221499d943386256feb9db46c119ff834bf79Yuqian Li    mCanvas->setMatrix(origM);
411afc221499d943386256feb9db46c119ff834bf79Yuqian Li}
412afc221499d943386256feb9db46c119ff834bf79Yuqian Li
413afc221499d943386256feb9db46c119ff834bf79Yuqian Li
4141db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
4151db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        const SkPaint& paint) {
41609bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger    SkPaint runPaint = paint;
41709bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger
41809bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger     SkTextBlobRunIterator it(blob);
41909bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger     for (;!it.done(); it.next()) {
42009bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         size_t textLen = it.glyphCount() * sizeof(uint16_t);
42109bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         const SkPoint& offset = it.offset();
42209bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         // applyFontToPaint() always overwrites the exact same attributes,
42309bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         // so it is safe to not re-seed the paint for this reason.
42409bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         it.applyFontToPaint(&runPaint);
42509bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger
42609bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         switch (it.positioning()) {
42709bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         case SkTextBlob::kDefault_Positioning:
42809bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             this->drawText(it.glyphs(), textLen, x + offset.x(), y + offset.y(), runPaint);
42909bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             break;
43009bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         case SkTextBlob::kHorizontal_Positioning: {
43109bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
43209bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             for (size_t i = 0; i < it.glyphCount(); i++) {
43309bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger                 pts[i].set(x + offset.x() + it.pos()[i], y + offset.y());
43409bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             }
43509bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
43609bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             break;
43709bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         }
43809bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         case SkTextBlob::kFull_Positioning: {
43909bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
44009bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             for (size_t i = 0; i < it.glyphCount(); i++) {
44109bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger                 const size_t xIndex = i*2;
44209bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger                 const size_t yIndex = xIndex + 1;
44309bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger                 pts[i].set(x + offset.x() + it.pos()[xIndex], y + offset.y() + it.pos()[yIndex]);
44409bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             }
44509bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
44609bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             break;
44709bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         }
44809bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         default:
44909bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger             SkFAIL("unhandled positioning mode");
45009bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger         }
45109bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger     }
4521db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
4531db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4541db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
455c2f31df8b3b9a237e9abffc59c61804ad8495073Mike Reed        const SkPoint texCoords[4], SkBlendMode bmode, const SkPaint& paint) {
456b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    if (mFilterHwuiCalls) {
457b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson        return;
458b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    }
4591db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkPatchUtils::VertexData data;
4601db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4611db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkMatrix matrix;
4621db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->getMatrix(&matrix);
4631db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &matrix);
4641db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4651db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // It automatically adjusts lodX and lodY in case it exceeds the number of indices.
4661db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // If it fails to generate the vertices, then we do not draw.
4671db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    if (SkPatchUtils::getVertexData(&data, cubics, colors, texCoords, lod.width(), lod.height())) {
4681db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        this->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCount, data.fPoints,
469c2f31df8b3b9a237e9abffc59c61804ad8495073Mike Reed                           data.fTexCoords, data.fColors, bmode, data.fIndices, data.fIndexCount,
4701db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger                           paint);
4711db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
4721db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
4731db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4746e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reedvoid SkiaCanvasProxy::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle) {
4751db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->clipRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, op);
4761db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
4771db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4786e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reedvoid SkiaCanvasProxy::onClipRRect(const SkRRect& roundRect, SkClipOp op, ClipEdgeStyle) {
4791db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkPath path;
4801db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    path.addRRect(roundRect);
4811db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->clipPath(&path, op);
4821db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
4831db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4846e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reedvoid SkiaCanvasProxy::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle) {
4851db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->clipPath(&path, op);
4861db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
4871db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4881db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}; // namespace uirenderer
4891db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}; // namespace android
490