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
23770e0b500793bce45442b5f403913d14017df4e8Stan Iliev#include <SkLatticeIter.h>
24a11ee3c4131d889d57b7d2cf30faa7c105b23b10Ben Wagner#include <SkPaint.h>
251bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include <SkPatchUtils.h>
26a11ee3c4131d889d57b7d2cf30faa7c105b23b10Ben Wagner#include <SkPath.h>
2717c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson#include <SkPixelRef.h>
28a11ee3c4131d889d57b7d2cf30faa7c105b23b10Ben Wagner#include <SkRRect.h>
29afc221499d943386256feb9db46c119ff834bf79Yuqian Li#include <SkRSXform.h>
301bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include <SkRect.h>
3179fc3b1f1675364dbb739ffa511a68ed5a80f357Matt Sarett#include <SkSurface.h>
3209bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger#include <SkTextBlobRunIterator.h>
33871cd2dd6074544bd41a84ff38255d81a392546aMike Reed#include <SkVertices.h>
341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include "hwui/Bitmap.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[],
491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                   const SkPaint& paint) {
50b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    if (!pts || count == 0) {
51b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson        return;
52b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    }
53b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson
541db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // convert the SkPoints into floats
551bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    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]);
751bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                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();
981bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        mCanvas->drawRoundRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, radii.fX, radii.fY,
991bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                               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) {
1091bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    mCanvas->drawArc(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, startAngle, sweepAngle,
1101bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                     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,
1181bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                   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();
1241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        mCanvas->drawBitmap(
1251bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                *hwuiBitmap, origin.fX, origin.fY, origin.fX + bitmap.dimensions().width(),
1261bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                origin.fY + bitmap.dimensions().height(), left, top,
1271bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                left + bitmap.dimensions().width(), top + bitmap.dimensions().height(), paint);
12817c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson    } else {
129aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        mCanvas->drawBitmap(*hwuiBitmap, left, top, paint);
13017c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson    }
1311db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
1321db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
133fc9999505a36c66892d7ccce85187936105f4f36sergeyvvoid SkiaCanvasProxy::onDrawBitmapRect(const SkBitmap& skBitmap, const SkRect* srcPtr,
1341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                       const SkRect& dst, const SkPaint* paint, SrcRectConstraint) {
135fc9999505a36c66892d7ccce85187936105f4f36sergeyv    SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(skBitmap.width(), skBitmap.height());
13617c5adfa63872fbb6a903a5941e3c6455995b92dTom Hudson    // TODO: if bitmap is a subset, do we need to add pixelRefOrigin to src?
1371bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    Bitmap* bitmap = reinterpret_cast<Bitmap*>(skBitmap.pixelRef());
1381bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, dst.fLeft, dst.fTop,
1391bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                        dst.fRight, dst.fBottom, paint);
1401db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
1411db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
1421db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
1431bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                       const SkRect& dst, const SkPaint*) {
1441bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    // TODO make nine-patch drawing a method on Canvas.h
1451db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkDEBUGFAIL("SkiaCanvasProxy::onDrawBitmapNine is not yet supported");
1461db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
1471db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
148770e0b500793bce45442b5f403913d14017df4e8Stan Ilievvoid SkiaCanvasProxy::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
1491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                  const SkPaint* paint) {
150770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    SkBitmap skiaBitmap;
1510a3ff952a6ba9ce15f8165632e606587fabd3feaStan Iliev    SkPixmap pixmap;
1520a3ff952a6ba9ce15f8165632e606587fabd3feaStan Iliev    if (image->peekPixels(&pixmap) && skiaBitmap.installPixels(pixmap)) {
153770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        onDrawBitmap(skiaBitmap, left, top, paint);
154770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    }
155770e0b500793bce45442b5f403913d14017df4e8Stan Iliev}
156770e0b500793bce45442b5f403913d14017df4e8Stan Iliev
157770e0b500793bce45442b5f403913d14017df4e8Stan Ilievvoid SkiaCanvasProxy::onDrawImageRect(const SkImage* image, const SkRect* srcPtr, const SkRect& dst,
1581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                      const SkPaint* paint, SrcRectConstraint constraint) {
159770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    SkBitmap skiaBitmap;
1600a3ff952a6ba9ce15f8165632e606587fabd3feaStan Iliev    SkPixmap pixmap;
1610a3ff952a6ba9ce15f8165632e606587fabd3feaStan Iliev    if (image->peekPixels(&pixmap) && skiaBitmap.installPixels(pixmap)) {
162770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        sk_sp<Bitmap> bitmap = Bitmap::createFrom(skiaBitmap.info(), *skiaBitmap.pixelRef());
163770e0b500793bce45442b5f403913d14017df4e8Stan Iliev        SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(image->width(), image->height());
1641bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, dst.fLeft,
1651bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                            dst.fTop, dst.fRight, dst.fBottom, paint);
166770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    }
167770e0b500793bce45442b5f403913d14017df4e8Stan Iliev}
168770e0b500793bce45442b5f403913d14017df4e8Stan Iliev
169770e0b500793bce45442b5f403913d14017df4e8Stan Ilievvoid SkiaCanvasProxy::onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
1701bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                      const SkPaint*) {
171770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    SkDEBUGFAIL("SkiaCanvasProxy::onDrawImageNine is not yet supported");
172770e0b500793bce45442b5f403913d14017df4e8Stan Iliev}
173770e0b500793bce45442b5f403913d14017df4e8Stan Iliev
174770e0b500793bce45442b5f403913d14017df4e8Stan Ilievvoid SkiaCanvasProxy::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
1751bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                         const SkRect& dst, const SkPaint* paint) {
176770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    SkLatticeIter iter(lattice, dst);
177770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    SkRect srcR, dstR;
178770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    while (iter.next(&srcR, &dstR)) {
1796c2a9e2bc1759ae7eefc973941e8a6fc6b3e912cDerek Sollenberger        onDrawImageRect(image, &srcR, dstR, paint, SkCanvas::kFast_SrcRectConstraint);
180770e0b500793bce45442b5f403913d14017df4e8Stan Iliev    }
181770e0b500793bce45442b5f403913d14017df4e8Stan Iliev}
182770e0b500793bce45442b5f403913d14017df4e8Stan Iliev
183871cd2dd6074544bd41a84ff38255d81a392546aMike Reedvoid SkiaCanvasProxy::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
1841bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                           const SkPaint& paint) {
185b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    if (mFilterHwuiCalls) {
186b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson        return;
187b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    }
188826deefda55ead0036cdb0924bc14f17d2a85420Mike Reed    mCanvas->drawVertices(vertices, bmode, paint);
1891db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
1901db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
19179fc3b1f1675364dbb739ffa511a68ed5a80f357Matt Sarettsk_sp<SkSurface> SkiaCanvasProxy::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
1921db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkDEBUGFAIL("SkiaCanvasProxy::onNewSurface is not supported");
1931db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    return NULL;
1941db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
1951db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
1961db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::willSave() {
197eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    mCanvas->save(android::SaveFlags::MatrixClip);
198eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita}
199eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita
200eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malitastatic inline SaveFlags::Flags saveFlags(SkCanvas::SaveLayerFlags layerFlags) {
201eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    SaveFlags::Flags saveFlags = 0;
202eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita
203eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    if (!(layerFlags & SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag)) {
204eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        saveFlags |= SaveFlags::ClipToLayer;
205eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    }
206eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita
207eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    return saveFlags;
2081db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2091db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2101bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John ReckSkCanvas::SaveLayerStrategy SkiaCanvasProxy::getSaveLayerStrategy(
2111bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        const SaveLayerRec& saveLayerRec) {
2121db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkRect rect;
2135518e7cbd4e8d7a7cb3d60a4251eccc3b7fb82dbLeon Scroggins III    if (saveLayerRec.fBounds) {
2145518e7cbd4e8d7a7cb3d60a4251eccc3b7fb82dbLeon Scroggins III        rect = *saveLayerRec.fBounds;
2155518e7cbd4e8d7a7cb3d60a4251eccc3b7fb82dbLeon Scroggins III    } else if (!mCanvas->getClipBounds(&rect)) {
2161db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        rect = SkRect::MakeEmpty();
2171db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
2185518e7cbd4e8d7a7cb3d60a4251eccc3b7fb82dbLeon Scroggins III    mCanvas->saveLayer(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, saveLayerRec.fPaint,
219eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita                       saveFlags(saveLayerRec.fSaveLayerFlags));
2201db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    return SkCanvas::kNoLayer_SaveLayerStrategy;
2211db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2221db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2231db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::willRestore() {
2241db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->restore();
2251db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2261db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2271db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::didConcat(const SkMatrix& matrix) {
2281db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->concat(matrix);
2291db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2301db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2311db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::didSetMatrix(const SkMatrix& matrix) {
2326daa13c5fa7577fa1d8371deca446f6ca911f38fChris Craik    mCanvas->setMatrix(matrix);
2331db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2341db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2351db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2361bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                   const SkPaint& paint) {
2371db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkPath path;
2381db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    path.addRRect(outer);
2391db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    path.addRRect(inner);
2401db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    path.setFillType(SkPath::kEvenOdd_FillType);
2411db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    this->drawPath(path, paint);
2421db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
2431db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2441db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger/**
2451db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * Utility class that converts the incoming text & paint from the given encoding
2461db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger * into glyphIDs.
2471db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger */
2481db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergerclass GlyphIDConverter {
2491db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergerpublic:
2501db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    GlyphIDConverter(const void* text, size_t byteLength, const SkPaint& origPaint) {
2511db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        paint = origPaint;
2521db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        if (paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding) {
2531db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            glyphIDs = (uint16_t*)text;
2541db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            count = byteLength >> 1;
2551db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        } else {
2561bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            // ensure space for one glyph per ID given UTF8 encoding.
2576bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner            storage.reset(new uint16_t[byteLength]);
2581db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            glyphIDs = storage.get();
2591db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            count = paint.textToGlyphs(text, byteLength, storage.get());
2601db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
2611db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
2621db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
2631db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2641db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkPaint paint;
2651db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    uint16_t* glyphIDs;
2661db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    int count;
2671bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
2681db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergerprivate:
2696bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner    std::unique_ptr<uint16_t[]> storage;
2701db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger};
2711db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2721db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2731bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                 const SkPaint& origPaint) {
2741db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // convert to glyphIDs if necessary
2751db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    GlyphIDConverter glyphs(text, byteLength, origPaint);
2761db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2771db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // compute the glyph positions
2786bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner    std::unique_ptr<SkScalar[]> glyphWidths(new SkScalar[glyphs.count]);
2791db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    glyphs.paint.getTextWidths(glyphs.glyphIDs, glyphs.count << 1, glyphWidths.get());
2801db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2811db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // compute conservative bounds
2821db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // NOTE: We could call the faster paint.getFontBounds for a less accurate,
2831db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    //       but even more conservative bounds if this  is too slow.
2841db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkRect bounds;
2851db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    glyphs.paint.measureText(glyphs.glyphIDs, glyphs.count << 1, &bounds);
2861db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
2871db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // adjust for non-left alignment
2881db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    if (glyphs.paint.getTextAlign() != SkPaint::kLeft_Align) {
2891db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        SkScalar stop = 0;
2901db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        for (int i = 0; i < glyphs.count; i++) {
2911db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            stop += glyphWidths[i];
2921db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
2931db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        if (glyphs.paint.getTextAlign() == SkPaint::kCenter_Align) {
2941db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            stop = SkScalarHalf(stop);
2951db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
2961db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        if (glyphs.paint.isVerticalText()) {
2971db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            y -= stop;
2981db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        } else {
2991db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger            x -= stop;
3001db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        }
3011db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
3021db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3031db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // setup the first glyph position and adjust bounds if needed
304806a6f07a37c16b37631d8707dd1f2b41276fafcTom Hudson    int xBaseline = 0;
305806a6f07a37c16b37631d8707dd1f2b41276fafcTom Hudson    int yBaseline = 0;
3061db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    if (mCanvas->drawTextAbsolutePos()) {
3071bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        bounds.offset(x, y);
308806a6f07a37c16b37631d8707dd1f2b41276fafcTom Hudson        xBaseline = x;
309806a6f07a37c16b37631d8707dd1f2b41276fafcTom Hudson        yBaseline = y;
3101db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
3111db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3121bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    static_assert(sizeof(SkPoint) == sizeof(float) * 2, "SkPoint is no longer two floats");
3131bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    auto glyphFunc = [&](uint16_t* text, float* positions) {
3141bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        memcpy(text, glyphs.glyphIDs, glyphs.count * sizeof(uint16_t));
3150b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev        size_t posIndex = 0;
3160b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev        // setup the first glyph position
3170b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev        positions[posIndex++] = xBaseline;
3180b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev        positions[posIndex++] = yBaseline;
3190b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev        // setup the remaining glyph positions
3200b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev        if (glyphs.paint.isVerticalText()) {
3210b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev            float yPosition = yBaseline;
3220b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev            for (int i = 1; i < glyphs.count; i++) {
3230b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev                positions[posIndex++] = xBaseline;
3241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                yPosition += glyphWidths[i - 1];
3250b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev                positions[posIndex++] = yPosition;
3260b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev            }
3270b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev        } else {
3280b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev            float xPosition = xBaseline;
3290b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev            for (int i = 1; i < glyphs.count; i++) {
3301bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                xPosition += glyphWidths[i - 1];
3310b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev                positions[posIndex++] = xPosition;
3320b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev                positions[posIndex++] = yBaseline;
3330b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev            }
3340b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev        }
3350b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev    };
3360b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev    mCanvas->drawGlyphs(glyphFunc, glyphs.count, glyphs.paint, x, y, bounds.fLeft, bounds.fTop,
3371bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                        bounds.fRight, bounds.fBottom, 0);
3381db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
3391db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3401db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
3411bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                    const SkPaint& origPaint) {
3421db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // convert to glyphIDs if necessary
3431db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    GlyphIDConverter glyphs(text, byteLength, origPaint);
3441db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3451db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    // convert to relative positions if necessary
3461db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    int x, y;
3471db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    if (mCanvas->drawTextAbsolutePos()) {
3481db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        x = 0;
3491db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        y = 0;
3501db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    } else {
3511db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        x = pos[0].fX;
3521db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        y = pos[0].fY;
3531db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
3541db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
35535934cccabf72879603ef37222da2195445f027eDerek Sollenberger    // Compute conservative bounds.  If the content has already been processed
35635934cccabf72879603ef37222da2195445f027eDerek Sollenberger    // by Minikin then it had already computed these bounds.  Unfortunately,
35735934cccabf72879603ef37222da2195445f027eDerek Sollenberger    // there is no way to capture those bounds as part of the Skia drawPosText
35835934cccabf72879603ef37222da2195445f027eDerek Sollenberger    // API so we need to do that computation again here.
359d84d2ee3359af8478afd3f891d5d316af1a562edStan Iliev    SkRect bounds = SkRect::MakeEmpty();
36035934cccabf72879603ef37222da2195445f027eDerek Sollenberger    for (int i = 0; i < glyphs.count; i++) {
361d84d2ee3359af8478afd3f891d5d316af1a562edStan Iliev        SkRect glyphBounds = SkRect::MakeEmpty();
36235934cccabf72879603ef37222da2195445f027eDerek Sollenberger        glyphs.paint.measureText(&glyphs.glyphIDs[i], sizeof(uint16_t), &glyphBounds);
36335934cccabf72879603ef37222da2195445f027eDerek Sollenberger        glyphBounds.offset(pos[i].fX, pos[i].fY);
36435934cccabf72879603ef37222da2195445f027eDerek Sollenberger        bounds.join(glyphBounds);
36535934cccabf72879603ef37222da2195445f027eDerek Sollenberger    }
3661db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3671bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    static_assert(sizeof(SkPoint) == sizeof(float) * 2, "SkPoint is no longer two floats");
3681bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    auto glyphFunc = [&](uint16_t* text, float* positions) {
3691bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        memcpy(text, glyphs.glyphIDs, glyphs.count * sizeof(uint16_t));
3700b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev        if (mCanvas->drawTextAbsolutePos()) {
3711bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            memcpy(positions, pos, 2 * glyphs.count * sizeof(float));
3720b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev        } else {
3730b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev            for (int i = 0, posIndex = 0; i < glyphs.count; i++) {
3740b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev                positions[posIndex++] = pos[i].fX - x;
3750b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev                positions[posIndex++] = pos[i].fY - y;
3760b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev            }
3770b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev        }
3780b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev    };
3790b58d9928309e2c64c7cafad287e55a8151ab19aStan Iliev    mCanvas->drawGlyphs(glyphFunc, glyphs.count, glyphs.paint, x, y, bounds.fLeft, bounds.fTop,
3801bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                        bounds.fRight, bounds.fBottom, 0);
3811db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
3821db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3831db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
3841bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                     SkScalar constY, const SkPaint& paint) {
3851db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    const size_t pointCount = byteLength >> 1;
3866bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner    std::unique_ptr<SkPoint[]> pts(new SkPoint[pointCount]);
3871db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    for (size_t i = 0; i < pointCount; i++) {
3881db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger        pts[i].set(xpos[i], constY);
3891db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    }
3906bbf68d05a9deb335fc693b4a64651aea1b4e9e0Ben Wagner    this->onDrawPosText(text, byteLength, pts.get(), paint);
3911db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
3921db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
3931db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
3941bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                       const SkMatrix* matrix, const SkPaint& origPaint) {
395afc221499d943386256feb9db46c119ff834bf79Yuqian Li    SkDEBUGFAIL("SkiaCanvasProxy::onDrawTextOnPath is not supported");
3961db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
3971db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
398afc221499d943386256feb9db46c119ff834bf79Yuqian Livoid SkiaCanvasProxy::onDrawTextRSXform(const void* text, size_t byteLength,
3991bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                        const SkRSXform xform[], const SkRect* cullRect,
4001bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                        const SkPaint& paint) {
4011bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    GlyphIDConverter glyphs(text, byteLength, paint);  // Just get count
402afc221499d943386256feb9db46c119ff834bf79Yuqian Li    SkMatrix localM, currM, origM;
403afc221499d943386256feb9db46c119ff834bf79Yuqian Li    mCanvas->getMatrix(&currM);
404afc221499d943386256feb9db46c119ff834bf79Yuqian Li    origM = currM;
405afc221499d943386256feb9db46c119ff834bf79Yuqian Li    for (int i = 0; i < glyphs.count; i++) {
406afc221499d943386256feb9db46c119ff834bf79Yuqian Li        localM.setRSXform(*xform++);
407afc221499d943386256feb9db46c119ff834bf79Yuqian Li        currM.setConcat(origM, localM);
408afc221499d943386256feb9db46c119ff834bf79Yuqian Li        mCanvas->setMatrix(currM);
4091bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        this->onDrawText((char*)text + (byteLength / glyphs.count * i), byteLength / glyphs.count,
4101bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                         0, 0, paint);
411afc221499d943386256feb9db46c119ff834bf79Yuqian Li    }
412afc221499d943386256feb9db46c119ff834bf79Yuqian Li    mCanvas->setMatrix(origM);
413afc221499d943386256feb9db46c119ff834bf79Yuqian Li}
414afc221499d943386256feb9db46c119ff834bf79Yuqian Li
4151db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
4161bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                     const SkPaint& paint) {
41709bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger    SkPaint runPaint = paint;
41809bd6c201dd7b5dfaae45ebf413fe0a779eb0268Derek Sollenberger
4191bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    SkTextBlobRunIterator it(blob);
4201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    for (; !it.done(); it.next()) {
4211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        size_t textLen = it.glyphCount() * sizeof(uint16_t);
4221bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        const SkPoint& offset = it.offset();
4231bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        // applyFontToPaint() always overwrites the exact same attributes,
4241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        // so it is safe to not re-seed the paint for this reason.
4251bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        it.applyFontToPaint(&runPaint);
4261bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
4271bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        switch (it.positioning()) {
4281bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            case SkTextBlob::kDefault_Positioning:
4291bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                this->drawText(it.glyphs(), textLen, x + offset.x(), y + offset.y(), runPaint);
4301bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                break;
4311bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            case SkTextBlob::kHorizontal_Positioning: {
4321bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
4331bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                for (size_t i = 0; i < it.glyphCount(); i++) {
4341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                    pts[i].set(x + offset.x() + it.pos()[i], y + offset.y());
4351bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                }
4361bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
4371bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                break;
4381bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            }
4391bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            case SkTextBlob::kFull_Positioning: {
4401bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
4411bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                for (size_t i = 0; i < it.glyphCount(); i++) {
4421bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                    const size_t xIndex = i * 2;
4431bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                    const size_t yIndex = xIndex + 1;
4441bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                    pts[i].set(x + offset.x() + it.pos()[xIndex],
4451bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                               y + offset.y() + it.pos()[yIndex]);
4461bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                }
4471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
4481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                break;
4491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            }
4501bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            default:
4511bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                SK_ABORT("unhandled positioning mode");
4521bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        }
4531bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    }
4541db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
4551db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4561db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenbergervoid SkiaCanvasProxy::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
4571bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                  const SkPoint texCoords[4], SkBlendMode bmode,
4581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                  const SkPaint& paint) {
459b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    if (mFilterHwuiCalls) {
460b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson        return;
461b1476ae7d515d6c406b4367cfb4ada8ce2d116e1Tom Hudson    }
4621db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkMatrix matrix;
4631db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->getMatrix(&matrix);
4641db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &matrix);
4651db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4661bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    mCanvas->drawVertices(
4671bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            SkPatchUtils::MakeVertices(cubics, colors, texCoords, lod.width(), lod.height()).get(),
4681bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            bmode, paint);
4691db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
4701db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4716e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reedvoid SkiaCanvasProxy::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle) {
4721db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->clipRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, op);
4731db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
4741db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4756e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reedvoid SkiaCanvasProxy::onClipRRect(const SkRRect& roundRect, SkClipOp op, ClipEdgeStyle) {
4761db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    SkPath path;
4771db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    path.addRRect(roundRect);
4781db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->clipPath(&path, op);
4791db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
4801db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4816e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reedvoid SkiaCanvasProxy::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle) {
4821db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger    mCanvas->clipPath(&path, op);
4831db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}
4841db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger
4851bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // namespace uirenderer
4861bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // namespace android
487