180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTypes.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkDWriteGeometrySink.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFloatUtils.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPath.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <dwrite.h>
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <d2d1.h>
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkDWriteGeometrySink::SkDWriteGeometrySink(SkPath* path) : fRefCount(1), fPath(path) { }
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkDWriteGeometrySink::~SkDWriteGeometrySink() { }
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruHRESULT STDMETHODCALLTYPE SkDWriteGeometrySink::QueryInterface(REFIID iid, void **object) {
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == object) {
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return E_INVALIDARG;
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (iid == __uuidof(IUnknown) || iid == __uuidof(IDWriteGeometrySink)) {
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *object = static_cast<IDWriteGeometrySink*>(this);
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->AddRef();
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return S_OK;
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *object = NULL;
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return E_NOINTERFACE;
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruULONG STDMETHODCALLTYPE SkDWriteGeometrySink::AddRef(void) {
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return static_cast<ULONG>(InterlockedIncrement(&fRefCount));
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruULONG STDMETHODCALLTYPE SkDWriteGeometrySink::Release(void) {
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ULONG res = static_cast<ULONG>(InterlockedDecrement(&fRefCount));
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == res) {
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete this;
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return res;
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid STDMETHODCALLTYPE SkDWriteGeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) {
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (fillMode) {
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    case D2D1_FILL_MODE_ALTERNATE:
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fPath->setFillType(SkPath::kEvenOdd_FillType);
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        break;
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    case D2D1_FILL_MODE_WINDING:
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fPath->setFillType(SkPath::kWinding_FillType);
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        break;
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    default:
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(!"Unknown D2D1_FILL_MODE.");
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        break;
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid STDMETHODCALLTYPE SkDWriteGeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags) {
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (vertexFlags == D2D1_PATH_SEGMENT_NONE || vertexFlags == D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN) {
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(!"Invalid D2D1_PATH_SEGMENT value.");
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid STDMETHODCALLTYPE SkDWriteGeometrySink::BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) {
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fPath->moveTo(SkFloatToScalar(startPoint.x), SkFloatToScalar(startPoint.y));
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (figureBegin == D2D1_FIGURE_BEGIN_HOLLOW) {
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(!"Invalid D2D1_FIGURE_BEGIN value.");
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid STDMETHODCALLTYPE SkDWriteGeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount) {
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (const D2D1_POINT_2F *end = &points[pointsCount]; points < end; ++points) {
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fPath->lineTo(SkFloatToScalar(points->x), SkFloatToScalar(points->y));
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool approximately_equal(float a, float b) {
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkFloatingPoint<float, 10> lhs(a), rhs(b);
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return lhs.AlmostEquals(rhs);
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutypedef struct {
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float x;
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float y;
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} Cubic[4], Quadratic[3];
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool check_quadratic(const Cubic& cubic, Quadratic& reduction) {
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float dx10 = cubic[1].x - cubic[0].x;
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float dx23 = cubic[2].x - cubic[3].x;
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float midX = cubic[0].x + dx10 * 3 / 2;
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //NOTE: !approximately_equal(midX - cubic[3].x, dx23 * 3 / 2)
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //does not work as subnormals get in between the left side and 0.
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!approximately_equal(midX, (dx23 * 3 / 2) + cubic[3].x)) {
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float dy10 = cubic[1].y - cubic[0].y;
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float dy23 = cubic[2].y - cubic[3].y;
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float midY = cubic[0].y + dy10 * 3 / 2;
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!approximately_equal(midY, (dy23 * 3 / 2) + cubic[3].y)) {
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    reduction[0] = cubic[0];
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    reduction[1].x = midX;
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    reduction[1].y = midY;
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    reduction[2] = cubic[3];
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid STDMETHODCALLTYPE SkDWriteGeometrySink::AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, UINT beziersCount) {
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPoint lastPt;
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fPath->getLastPt(&lastPt);
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    D2D1_POINT_2F prevPt = { SkScalarToFloat(lastPt.fX), SkScalarToFloat(lastPt.fY) };
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (const D2D1_BEZIER_SEGMENT *end = &beziers[beziersCount]; beziers < end; ++beziers) {
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Cubic cubic = { { prevPt.x, prevPt.y },
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        { beziers->point1.x, beziers->point1.y },
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        { beziers->point2.x, beziers->point2.y },
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        { beziers->point3.x, beziers->point3.y }, };
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Quadratic quadratic;
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (check_quadratic(cubic, quadratic)) {
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fPath->quadTo(SkFloatToScalar(quadratic[1].x), SkFloatToScalar(quadratic[1].y),
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          SkFloatToScalar(quadratic[2].x), SkFloatToScalar(quadratic[2].y));
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fPath->cubicTo(SkFloatToScalar(beziers->point1.x), SkFloatToScalar(beziers->point1.y),
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           SkFloatToScalar(beziers->point2.x), SkFloatToScalar(beziers->point2.y),
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           SkFloatToScalar(beziers->point3.x), SkFloatToScalar(beziers->point3.y));
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        prevPt = beziers->point3;
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid STDMETHODCALLTYPE SkDWriteGeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) {
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fPath->close();
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruHRESULT SkDWriteGeometrySink::Close() {
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return S_OK;
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruHRESULT SkDWriteGeometrySink::Create(SkPath* path, IDWriteGeometrySink** geometryToPath) {
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *geometryToPath = new SkDWriteGeometrySink(path);
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return S_OK;
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
147