From: subhransu mohanty Date: Mon, 30 Jul 2018 03:03:49 +0000 (+0900) Subject: lottie: Follow Tizen coding guideline. X-Git-Tag: submit/tizen/20180917.042405~169 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9e63597b976461e88eefad402672f1b551cd0eda;p=platform%2Fcore%2Fuifw%2Flottie-player.git lottie: Follow Tizen coding guideline. Change-Id: Ice6a5af7cb08e768e157f8bb45bef64bb4062dce --- diff --git a/inc/lottieplayer.h b/inc/lottieplayer.h index c7fd5c9..795a347 100644 --- a/inc/lottieplayer.h +++ b/inc/lottieplayer.h @@ -1,36 +1,35 @@ #ifndef LOTPLAYER_H #define LOTPLAYER_H -#include #include +#include #ifdef _WIN32 -# ifdef LOT_BUILD -# ifdef DLL_EXPORT -# define LOT_EXPORT __declspec(dllexport) -# else -# define LOT_EXPORT -# endif -# else -# define LOT_EXPORT __declspec(dllimport) -# endif +#ifdef LOT_BUILD +#ifdef DLL_EXPORT +#define LOT_EXPORT __declspec(dllexport) +#else +#define LOT_EXPORT +#endif +#else +#define LOT_EXPORT __declspec(dllimport) +#endif +#else +#ifdef __GNUC__ +#if __GNUC__ >= 4 +#define LOT_EXPORT __attribute__((visibility("default"))) #else -# ifdef __GNUC__ -# if __GNUC__ >= 4 -# define LOT_EXPORT __attribute__ ((visibility("default"))) -# else -# define LOT_EXPORT -# endif -# else -# define LOT_EXPORT -# endif +#define LOT_EXPORT +#endif +#else +#define LOT_EXPORT +#endif #endif class LOTPlayerPrivate; class LOTNode; -struct LOT_EXPORT LOTBuffer -{ +struct LOT_EXPORT LOTBuffer { uint32_t *buffer; int width; int height; @@ -38,8 +37,7 @@ struct LOT_EXPORT LOTBuffer bool clear; }; -class LOT_EXPORT LOTPlayer -{ +class LOT_EXPORT LOTPlayer { public: ~LOTPlayer(); LOTPlayer(); @@ -48,75 +46,57 @@ public: float playTime() const; - void setPos(float pos); + void setPos(float pos); float pos(); - const std::vector& renderList() const; + const std::vector &renderList() const; - //TODO: Consider correct position... - void setSize(int width, int height); - void size(int &width, int &height) const; + // TODO: Consider correct position... + void setSize(int width, int height); + void size(int &width, int &height) const; std::future render(float pos, LOTBuffer &buffer); - bool renderSync(float pos, LOTBuffer &buffer); + bool renderSync(float pos, LOTBuffer &buffer); public: - LOTPlayerPrivate *d; + LOTPlayerPrivate *d; }; -#define ChangeFlagNone 0x0000 -#define ChangeFlagPath 0x0001 +#define ChangeFlagNone 0x0000 +#define ChangeFlagPath 0x0001 #define ChangeFlagPaint 0x0010 -#define ChangeFlagAll (ChangeFlagPath & ChangeFlagPaint) +#define ChangeFlagAll (ChangeFlagPath & ChangeFlagPaint) -class LOT_EXPORT LOTNode -{ +class LOT_EXPORT LOTNode { public: struct PathData { const float *ptPtr; int ptCount; - const char *elmPtr; + const char * elmPtr; int elmCount; }; struct Color { unsigned short r, g, b, a; }; - enum BrushType { - BrushSolid, - BrushGradient - }; - enum FillRule { - EvenOdd, - Winding - }; + enum BrushType { BrushSolid, BrushGradient }; + enum FillRule { EvenOdd, Winding }; - enum JoinStyle { - MiterJoin, - BevelJoin, - RoundJoin - }; + enum JoinStyle { MiterJoin, BevelJoin, RoundJoin }; - enum CapStyle { - FlatCap, - SquareCap, - RoundCap - }; + enum CapStyle { FlatCap, SquareCap, RoundCap }; struct Stroke { - bool enable; - int width; - CapStyle cap; - JoinStyle join; - int meterLimit; - float *dashArray; - int dashArraySize; + bool enable; + int width; + CapStyle cap; + JoinStyle join; + int meterLimit; + float * dashArray; + int dashArraySize; }; struct Gradient { - enum Type { - Linear = 1, - Radial = 2 - }; + enum Type { Linear = 1, Radial = 2 }; Gradient::Type type; struct { float x, y; @@ -132,13 +112,13 @@ public: LOTNode(); public: - int mFlag; - LOTNode::BrushType mType; - FillRule mFillRule; - PathData mPath; - Color mColor; - Stroke mStroke; - Gradient mGradient; + int mFlag; + LOTNode::BrushType mType; + FillRule mFillRule; + PathData mPath; + Color mColor; + Stroke mStroke; + Gradient mGradient; }; -#endif // LOTPLAYER_H +#endif // LOTPLAYER_H diff --git a/src/lottie/lottieitem.cpp b/src/lottie/lottieitem.cpp index cc5c02e..bef0c2d 100644 --- a/src/lottie/lottieitem.cpp +++ b/src/lottie/lottieitem.cpp @@ -1,145 +1,146 @@ #include "lottieitem.h" -#include"vbitmap.h" -#include"vpainter.h" -#include"vraster.h" -#include"vdasher.h" #include +#include "vbitmap.h" +#include "vdasher.h" +#include "vpainter.h" +#include "vraster.h" /* Lottie Layer Rules - * 1. time stretch is pre calculated and applied to all the properties of the lottilayer model and all its children - * 2. The frame property could be reversed using,time-reverse layer property in AE. which means (start frame > endFrame) - * 3. + * 1. time stretch is pre calculated and applied to all the properties of the + * lottilayer model and all its children + * 2. The frame property could be reversed using,time-reverse layer property in + * AE. which means (start frame > endFrame) 3. */ -LOTCompItem::LOTCompItem(LOTModel *model):mRootModel(model), mUpdateViewBox(false),mCurFrameNo(-1) -{ - // 1. build layer item list - mCompData = model->mRoot.get(); - for(auto i : mCompData->mChildren) { - LOTLayerData *layerData = dynamic_cast(i.get()); - if (layerData) { - LOTLayerItem *layerItem = LOTCompItem::createLayerItem(layerData); - if (layerItem) { - mLayers.push_back(layerItem); - mLayerMap[layerItem->id()] = layerItem; - } - } - } - - //2. update parent layer - for(auto i : mLayers) { - int id = i->parentId(); - if (id >=0) { - auto search = mLayerMap.find(id); - if (search != mLayerMap.end()) { - LOTLayerItem *parentLayer = search->second; - i->setParentLayer(parentLayer); - } - } - } - //3. update static property of each layer - for(auto i : mLayers) { - i->updateStaticProperty(); - } - - mViewSize = mCompData->size(); +LOTCompItem::LOTCompItem(LOTModel *model) + : mRootModel(model), mUpdateViewBox(false), mCurFrameNo(-1) +{ + // 1. build layer item list + mCompData = model->mRoot.get(); + for (auto i : mCompData->mChildren) { + LOTLayerData *layerData = dynamic_cast(i.get()); + if (layerData) { + LOTLayerItem *layerItem = LOTCompItem::createLayerItem(layerData); + if (layerItem) { + mLayers.push_back(layerItem); + mLayerMap[layerItem->id()] = layerItem; + } + } + } + + // 2. update parent layer + for (auto i : mLayers) { + int id = i->parentId(); + if (id >= 0) { + auto search = mLayerMap.find(id); + if (search != mLayerMap.end()) { + LOTLayerItem *parentLayer = search->second; + i->setParentLayer(parentLayer); + } + } + } + // 3. update static property of each layer + for (auto i : mLayers) { + i->updateStaticProperty(); + } + + mViewSize = mCompData->size(); } LOTCompItem::~LOTCompItem() { - for(auto i : mLayers) { - delete i; + for (auto i : mLayers) { + delete i; } } -LOTLayerItem * -LOTCompItem::createLayerItem(LOTLayerData *layerData) +LOTLayerItem *LOTCompItem::createLayerItem(LOTLayerData *layerData) { - switch(layerData->mLayerType) { - case LayerType::Precomp: { - return new LOTCompLayerItem(layerData); - break; - } - case LayerType::Solid: { - return new LOTSolidLayerItem(layerData); - break; - } - case LayerType::Shape: { - return new LOTShapeLayerItem(layerData); - break; - } - case LayerType::Null: { - return new LOTNullLayerItem(layerData); - break; - } - default: - return nullptr; - break; + switch (layerData->mLayerType) { + case LayerType::Precomp: { + return new LOTCompLayerItem(layerData); + break; + } + case LayerType::Solid: { + return new LOTSolidLayerItem(layerData); + break; + } + case LayerType::Shape: { + return new LOTShapeLayerItem(layerData); + break; + } + case LayerType::Null: { + return new LOTNullLayerItem(layerData); + break; + } + default: + return nullptr; + break; } } void LOTCompItem::resize(const VSize &size) { - if (mViewSize == size) return; - mViewSize = size; - mUpdateViewBox = true; + if (mViewSize == size) return; + mViewSize = size; + mUpdateViewBox = true; } VSize LOTCompItem::size() const { - return mViewSize; + return mViewSize; } bool LOTCompItem::update(int frameNo) { - // check if cached frame is same as requested frame. - if (!mUpdateViewBox && (mCurFrameNo == frameNo)) return false; - - /* - * if viewbox dosen't scale exactly to the viewport - * we scale the viewbox keeping AspectRatioPreserved and then align the - * viewbox to the viewport using AlignCenter rule. - */ - VSize viewPort = mViewSize; - VSize viewBox = mCompData->size(); - - float sx = float(viewPort.width()) / viewBox.width(); - float sy = float(viewPort.height()) / viewBox.height(); - float scale = fmin(sx, sy); - float tx = (viewPort.width() - viewBox.width() * scale) * 0.5; - float ty = (viewPort.height() - viewBox.height() * scale) * 0.5; - - VMatrix m; - m.scale(scale, scale).translate(tx, ty); - - // update the layer from back to front - for (auto i = mLayers.rbegin(); i != mLayers.rend(); ++i) { - LOTLayerItem *layer = *i; - layer->update(frameNo, m, 1.0); - } - buildRenderList(); - mCurFrameNo = frameNo; - mUpdateViewBox = false; - return true; + // check if cached frame is same as requested frame. + if (!mUpdateViewBox && (mCurFrameNo == frameNo)) return false; + + /* + * if viewbox dosen't scale exactly to the viewport + * we scale the viewbox keeping AspectRatioPreserved and then align the + * viewbox to the viewport using AlignCenter rule. + */ + VSize viewPort = mViewSize; + VSize viewBox = mCompData->size(); + + float sx = float(viewPort.width()) / viewBox.width(); + float sy = float(viewPort.height()) / viewBox.height(); + float scale = fmin(sx, sy); + float tx = (viewPort.width() - viewBox.width() * scale) * 0.5; + float ty = (viewPort.height() - viewBox.height() * scale) * 0.5; + + VMatrix m; + m.scale(scale, scale).translate(tx, ty); + + // update the layer from back to front + for (auto i = mLayers.rbegin(); i != mLayers.rend(); ++i) { + LOTLayerItem *layer = *i; + layer->update(frameNo, m, 1.0); + } + buildRenderList(); + mCurFrameNo = frameNo; + mUpdateViewBox = false; + return true; } void LOTCompItem::buildRenderList() { mDrawableList.clear(); for (auto i = mLayers.rbegin(); i != mLayers.rend(); ++i) { - LOTLayerItem *layer = *i; - layer->renderList(mDrawableList); + LOTLayerItem *layer = *i; + layer->renderList(mDrawableList); } mRenderList.clear(); - for(auto i : mDrawableList) { + for (auto i : mDrawableList) { LOTDrawable *lotDrawable = static_cast(i); lotDrawable->sync(); mRenderList.push_back(&lotDrawable->mCNode); } } -const std::vector& LOTCompItem::renderList() const +const std::vector &LOTCompItem::renderList() const { return mRenderList; } @@ -147,7 +148,8 @@ const std::vector& LOTCompItem::renderList() const bool LOTCompItem::render(const LOTBuffer &buffer) { VBitmap bitmap((uchar *)buffer.buffer, buffer.width, buffer.height, - buffer.bytesPerLine, VBitmap::Format::ARGB32_Premultiplied, nullptr, nullptr); + buffer.bytesPerLine, VBitmap::Format::ARGB32_Premultiplied, + nullptr, nullptr); /* schedule all preprocess task for this frame at once. */ @@ -156,10 +158,10 @@ bool LOTCompItem::render(const LOTBuffer &buffer) } VPainter painter(&bitmap); - VRle mask; + VRle mask; for (auto i = mLayers.rbegin(); i != mLayers.rend(); ++i) { - LOTLayerItem *layer = *i; - layer->render(&painter, mask); + LOTLayerItem *layer = *i; + layer->render(&painter, mask); } return true; @@ -191,8 +193,7 @@ VRle LOTMaskItem::rle() mRle = mRleTask.get(); if (!vCompare(mCombinedAlpha, 1.0f)) mRle = mRle * (mCombinedAlpha * 255); - if (mData->mInv) - mRle = ~mRle; + if (mData->mInv) mRle = ~mRle; } return mRle; } @@ -209,7 +210,7 @@ void LOTLayerItem::render(VPainter *painter, const VRle &inheritMask) mask = mask & inheritMask; } - for(auto i : list) { + for (auto i : list) { painter->setBrush(i->mBrush); if (!mask.isEmpty()) { VRle rle = i->rle() & mask; @@ -222,37 +223,37 @@ void LOTLayerItem::render(VPainter *painter, const VRle &inheritMask) VRle LOTLayerItem::maskRle(const VRect &clipRect) { - VRle rle; for (auto &i : mMasks) { switch (i->maskMode()) { - case LOTMaskData::Mode::Add: { - rle = rle + i->rle(); - break; - } - case LOTMaskData::Mode::Substarct: { - if (rle.isEmpty() && !clipRect.isEmpty()) - rle = VRle::toRle(clipRect); - rle = rle - i->rle(); - break; - } - case LOTMaskData::Mode::Intersect: { - rle = rle & i->rle(); - break; - } - default: - break; + case LOTMaskData::Mode::Add: { + rle = rle + i->rle(); + break; + } + case LOTMaskData::Mode::Substarct: { + if (rle.isEmpty() && !clipRect.isEmpty()) + rle = VRle::toRle(clipRect); + rle = rle - i->rle(); + break; + } + case LOTMaskData::Mode::Intersect: { + rle = rle & i->rle(); + break; + } + default: + break; } } return rle; } -LOTLayerItem::LOTLayerItem(LOTLayerData *layerData):mLayerData(layerData), - mParentLayer(nullptr), - mPrecompLayer(nullptr), - mCombinedAlpha(0.0f), - mFrameNo(-1), - mDirtyFlag(DirtyFlagBit::All) +LOTLayerItem::LOTLayerItem(LOTLayerData *layerData) + : mLayerData(layerData), + mParentLayer(nullptr), + mPrecompLayer(nullptr), + mCombinedAlpha(0.0f), + mFrameNo(-1), + mDirtyFlag(DirtyFlagBit::All) { if (mLayerData->mHasMask) { for (auto i : mLayerData->mMasks) { @@ -263,110 +264,107 @@ LOTLayerItem::LOTLayerItem(LOTLayerData *layerData):mLayerData(layerData), void LOTLayerItem::updateStaticProperty() { - if (mParentLayer) - mParentLayer->updateStaticProperty(); + if (mParentLayer) mParentLayer->updateStaticProperty(); - mStatic = mLayerData->isStatic(); - mStatic = mParentLayer ? (mStatic & mParentLayer->isStatic()) : mStatic; - mStatic = mPrecompLayer ? (mStatic & mPrecompLayer->isStatic()) : mStatic; + mStatic = mLayerData->isStatic(); + mStatic = mParentLayer ? (mStatic & mParentLayer->isStatic()) : mStatic; + mStatic = mPrecompLayer ? (mStatic & mPrecompLayer->isStatic()) : mStatic; } -void LOTLayerItem::update(int frameNo, const VMatrix &parentMatrix, float parentAlpha) +void LOTLayerItem::update(int frameNo, const VMatrix &parentMatrix, + float parentAlpha) { - mFrameNo = frameNo; - // 1. check if the layer is part of the current frame - if (!visible()) return; + mFrameNo = frameNo; + // 1. check if the layer is part of the current frame + if (!visible()) return; - // 2. calculate the parent matrix and alpha - VMatrix m = matrix(frameNo); - m *= parentMatrix; - float alpha = parentAlpha * opacity(frameNo); + // 2. calculate the parent matrix and alpha + VMatrix m = matrix(frameNo); + m *= parentMatrix; + float alpha = parentAlpha * opacity(frameNo); - //6. update the mask - if (hasMask()) { - for (auto &i : mMasks) - i->update(frameNo, m, alpha, mDirtyFlag); - } + // 6. update the mask + if (hasMask()) { + for (auto &i : mMasks) i->update(frameNo, m, alpha, mDirtyFlag); + } - // 3. update the dirty flag based on the change - if (!mCombinedMatrix.fuzzyCompare(m)) { - mDirtyFlag |= DirtyFlagBit::Matrix; - } - if (!vCompare(mCombinedAlpha, alpha)) { - mDirtyFlag |= DirtyFlagBit::Alpha; - } - mCombinedMatrix = m; - mCombinedAlpha = alpha; + // 3. update the dirty flag based on the change + if (!mCombinedMatrix.fuzzyCompare(m)) { + mDirtyFlag |= DirtyFlagBit::Matrix; + } + if (!vCompare(mCombinedAlpha, alpha)) { + mDirtyFlag |= DirtyFlagBit::Alpha; + } + mCombinedMatrix = m; + mCombinedAlpha = alpha; - // 4. if no parent property change and layer is static then nothing to do. - if ((flag() & DirtyFlagBit::None) && isStatic()) - return; + // 4. if no parent property change and layer is static then nothing to do. + if ((flag() & DirtyFlagBit::None) && isStatic()) return; - //5. update the content of the layer - updateContent(); + // 5. update the content of the layer + updateContent(); - //6. reset the dirty flag - mDirtyFlag = DirtyFlagBit::None; + // 6. reset the dirty flag + mDirtyFlag = DirtyFlagBit::None; } -float -LOTLayerItem::opacity(int frameNo) const +float LOTLayerItem::opacity(int frameNo) const { - return mLayerData->mTransform->opacity(frameNo); + return mLayerData->mTransform->opacity(frameNo); } -VMatrix -LOTLayerItem::matrix(int frameNo) const +VMatrix LOTLayerItem::matrix(int frameNo) const { if (mParentLayer) - return mLayerData->mTransform->matrix(frameNo) * mParentLayer->matrix(frameNo); + return mLayerData->mTransform->matrix(frameNo) * + mParentLayer->matrix(frameNo); else return mLayerData->mTransform->matrix(frameNo); } bool LOTLayerItem::visible() const { - if (frameNo() >= mLayerData->inFrame() && frameNo() < mLayerData->outFrame()) - return true; - else - return false; + if (frameNo() >= mLayerData->inFrame() && + frameNo() < mLayerData->outFrame()) + return true; + else + return false; } - - -LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel):LOTLayerItem(layerModel) +LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel) + : LOTLayerItem(layerModel) { - for(auto i : mLayerData->mChildren) { - LOTLayerData *layerModel = dynamic_cast(i.get()); - if (layerModel) { - LOTLayerItem *layerItem = LOTCompItem::createLayerItem(layerModel); - if (layerItem) { - mLayers.push_back(layerItem); - mLayerMap[layerItem->id()] = layerItem; - } - } - } + for (auto i : mLayerData->mChildren) { + LOTLayerData *layerModel = dynamic_cast(i.get()); + if (layerModel) { + LOTLayerItem *layerItem = LOTCompItem::createLayerItem(layerModel); + if (layerItem) { + mLayers.push_back(layerItem); + mLayerMap[layerItem->id()] = layerItem; + } + } + } - //2. update parent layer - for(auto i : mLayers) { - int id = i->parentId(); - if (id >=0) { - auto search = mLayerMap.find(id); - if (search != mLayerMap.end()) { - LOTLayerItem *parentLayer = search->second; - i->setParentLayer(parentLayer); - } - } - i->setPrecompLayer(this); - } + // 2. update parent layer + for (auto i : mLayers) { + int id = i->parentId(); + if (id >= 0) { + auto search = mLayerMap.find(id); + if (search != mLayerMap.end()) { + LOTLayerItem *parentLayer = search->second; + i->setParentLayer(parentLayer); + } + } + i->setPrecompLayer(this); + } } void LOTCompLayerItem::updateStaticProperty() { LOTLayerItem::updateStaticProperty(); - for(auto i : mLayers) { - i->updateStaticProperty(); + for (auto i : mLayers) { + i->updateStaticProperty(); } } @@ -381,15 +379,15 @@ void LOTCompLayerItem::render(VPainter *painter, const VRle &inheritMask) mask = mask & inheritMask; } - for(auto i : mLayers) { - i->render(painter, mask); + for (auto i : mLayers) { + i->render(painter, mask); } } LOTCompLayerItem::~LOTCompLayerItem() { - for(auto i : mLayers) { - delete i; + for (auto i : mLayers) { + delete i; } } @@ -397,8 +395,8 @@ void LOTCompLayerItem::updateContent() { // update the layer from back to front for (auto i = mLayers.rbegin(); i != mLayers.rend(); ++i) { - LOTLayerItem *layer = *i; - layer->update(frameNo(), combinedMatrix(), combinedAlpha()); + LOTLayerItem *layer = *i; + layer->update(frameNo(), combinedMatrix(), combinedAlpha()); } } @@ -408,37 +406,38 @@ void LOTCompLayerItem::renderList(std::vector &list) // update the layer from back to front for (auto i = mLayers.rbegin(); i != mLayers.rend(); ++i) { - LOTLayerItem *layer = *i; - layer->renderList(list); + LOTLayerItem *layer = *i; + layer->renderList(list); } } -LOTSolidLayerItem::LOTSolidLayerItem(LOTLayerData *layerData):LOTLayerItem(layerData) +LOTSolidLayerItem::LOTSolidLayerItem(LOTLayerData *layerData) + : LOTLayerItem(layerData) { - } void LOTSolidLayerItem::updateContent() { - if (!mRenderNode) { - mRenderNode = std::make_unique(); - mRenderNode->mType = VDrawable::Type::Fill; - mRenderNode->mFlag |= VDrawable::DirtyState::All; - } - - if (flag() & DirtyFlagBit::Matrix) { - VPath path; - path.addRect(VRectF(0, 0, mLayerData->solidWidth(), mLayerData->solidHeight())); - path.transform(combinedMatrix()); - mRenderNode->mFlag |= VDrawable::DirtyState::Path; - mRenderNode->mPath = path; - } - if (flag() & DirtyFlagBit::Alpha) { - LottieColor color = mLayerData->solidColor(); - VBrush brush(color.toColor(combinedAlpha())); - mRenderNode->setBrush(brush); - mRenderNode->mFlag |= VDrawable::DirtyState::Brush; - } + if (!mRenderNode) { + mRenderNode = std::make_unique(); + mRenderNode->mType = VDrawable::Type::Fill; + mRenderNode->mFlag |= VDrawable::DirtyState::All; + } + + if (flag() & DirtyFlagBit::Matrix) { + VPath path; + path.addRect( + VRectF(0, 0, mLayerData->solidWidth(), mLayerData->solidHeight())); + path.transform(combinedMatrix()); + mRenderNode->mFlag |= VDrawable::DirtyState::Path; + mRenderNode->mPath = path; + } + if (flag() & DirtyFlagBit::Alpha) { + LottieColor color = mLayerData->solidColor(); + VBrush brush(color.toColor(combinedAlpha())); + mRenderNode->setBrush(brush); + mRenderNode->mFlag |= VDrawable::DirtyState::Brush; + } } void LOTSolidLayerItem::renderList(std::vector &list) @@ -448,23 +447,19 @@ void LOTSolidLayerItem::renderList(std::vector &list) list.push_back(mRenderNode.get()); } -LOTNullLayerItem::LOTNullLayerItem(LOTLayerData *layerData):LOTLayerItem(layerData) +LOTNullLayerItem::LOTNullLayerItem(LOTLayerData *layerData) + : LOTLayerItem(layerData) { - } -void LOTNullLayerItem::updateContent() -{ - -} - +void LOTNullLayerItem::updateContent() {} -LOTShapeLayerItem::LOTShapeLayerItem(LOTLayerData *layerData):LOTLayerItem(layerData) +LOTShapeLayerItem::LOTShapeLayerItem(LOTLayerData *layerData) + : LOTLayerItem(layerData) { mRoot = new LOTContentGroupItem(nullptr); mRoot->addChildren(layerData); mRoot->processPaintOperation(); - if (layerData->hasPathOperator()) - mRoot->processTrimOperation(); + if (layerData->hasPathOperator()) mRoot->processTrimOperation(); } LOTShapeLayerItem::~LOTShapeLayerItem() @@ -472,62 +467,63 @@ LOTShapeLayerItem::~LOTShapeLayerItem() delete mRoot; } -LOTContentItem * LOTShapeLayerItem::createContentItem(LOTData *contentData) +LOTContentItem *LOTShapeLayerItem::createContentItem(LOTData *contentData) { - switch(contentData->type()) { - case LOTData::Type::ShapeGroup: { - return new LOTContentGroupItem(static_cast(contentData)); - break; - } - case LOTData::Type::Rect: { - return new LOTRectItem(static_cast(contentData)); - break; - } - case LOTData::Type::Ellipse: { - return new LOTEllipseItem(static_cast(contentData)); - break; - } - case LOTData::Type::Shape: { - return new LOTShapeItem(static_cast(contentData)); - break; - } - case LOTData::Type::Polystar: { - return new LOTPolystarItem(static_cast(contentData)); - break; - } - case LOTData::Type::Fill: { - return new LOTFillItem(static_cast(contentData)); - break; - } - case LOTData::Type::GFill: { - return new LOTGFillItem(static_cast(contentData)); - break; - } - case LOTData::Type::Stroke: { - return new LOTStrokeItem(static_cast(contentData)); - break; - } - case LOTData::Type::GStroke: { - return new LOTGStrokeItem(static_cast(contentData)); - break; - } - case LOTData::Type::Repeater: { - return new LOTRepeaterItem(static_cast(contentData)); - break; - } - case LOTData::Type::Trim: { - return new LOTTrimItem(static_cast(contentData)); - break; - } - default: - return nullptr; - break; + switch (contentData->type()) { + case LOTData::Type::ShapeGroup: { + return new LOTContentGroupItem( + static_cast(contentData)); + break; + } + case LOTData::Type::Rect: { + return new LOTRectItem(static_cast(contentData)); + break; + } + case LOTData::Type::Ellipse: { + return new LOTEllipseItem(static_cast(contentData)); + break; + } + case LOTData::Type::Shape: { + return new LOTShapeItem(static_cast(contentData)); + break; + } + case LOTData::Type::Polystar: { + return new LOTPolystarItem(static_cast(contentData)); + break; + } + case LOTData::Type::Fill: { + return new LOTFillItem(static_cast(contentData)); + break; + } + case LOTData::Type::GFill: { + return new LOTGFillItem(static_cast(contentData)); + break; + } + case LOTData::Type::Stroke: { + return new LOTStrokeItem(static_cast(contentData)); + break; + } + case LOTData::Type::GStroke: { + return new LOTGStrokeItem(static_cast(contentData)); + break; + } + case LOTData::Type::Repeater: { + return new LOTRepeaterItem(static_cast(contentData)); + break; + } + case LOTData::Type::Trim: { + return new LOTTrimItem(static_cast(contentData)); + break; + } + default: + return nullptr; + break; } } void LOTShapeLayerItem::updateContent() { - mRoot->update(frameNo(), combinedMatrix(), combinedAlpha(), flag()); + mRoot->update(frameNo(), combinedMatrix(), combinedAlpha(), flag()); } void LOTShapeLayerItem::renderList(std::vector &list) @@ -536,227 +532,235 @@ void LOTShapeLayerItem::renderList(std::vector &list) mRoot->renderList(list); } -LOTContentGroupItem::LOTContentGroupItem(LOTShapeGroupData *data):mData(data) +LOTContentGroupItem::LOTContentGroupItem(LOTShapeGroupData *data) : mData(data) { - addChildren(mData); + addChildren(mData); } void LOTContentGroupItem::addChildren(LOTGroupData *data) { - if (!data) return; + if (!data) return; - for(auto i : data->mChildren) { - LOTData *data = i.get(); - LOTContentItem *content = LOTShapeLayerItem::createContentItem(data); - if (content) - mContents.push_back(content); - } + for (auto i : data->mChildren) { + LOTData * data = i.get(); + LOTContentItem *content = LOTShapeLayerItem::createContentItem(data); + if (content) mContents.push_back(content); + } } LOTContentGroupItem::~LOTContentGroupItem() { - for(auto i : mContents) { + for (auto i : mContents) { delete i; } } - -void LOTContentGroupItem::update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) +void LOTContentGroupItem::update(int frameNo, const VMatrix &parentMatrix, + float parentAlpha, const DirtyFlag &flag) { - VMatrix m = parentMatrix; - float alpha = parentAlpha; - DirtyFlag newFlag = flag; + VMatrix m = parentMatrix; + float alpha = parentAlpha; + DirtyFlag newFlag = flag; - if (mData) { - // update the matrix and the flag - if ((flag & DirtyFlagBit::Matrix) || !mData->mTransform->staticMatrix() ) { - newFlag |= DirtyFlagBit::Matrix; - } - m = mData->mTransform->matrix(frameNo); - m *= parentMatrix; - alpha *= mData->mTransform->opacity(frameNo); + if (mData) { + // update the matrix and the flag + if ((flag & DirtyFlagBit::Matrix) || + !mData->mTransform->staticMatrix()) { + newFlag |= DirtyFlagBit::Matrix; + } + m = mData->mTransform->matrix(frameNo); + m *= parentMatrix; + alpha *= mData->mTransform->opacity(frameNo); - if (!vCompare(alpha, parentAlpha)) { - newFlag |= DirtyFlagBit::Alpha; - } - } + if (!vCompare(alpha, parentAlpha)) { + newFlag |= DirtyFlagBit::Alpha; + } + } - for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) { - (*i)->update(frameNo, m, alpha, newFlag); - } + for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) { + (*i)->update(frameNo, m, alpha, newFlag); + } } void LOTContentGroupItem::renderList(std::vector &list) { for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) { - (*i)->renderList(list); + (*i)->renderList(list); } } void LOTContentGroupItem::processPaintOperation() { - std::vector list; - paintOperationHelper(list); + std::vector list; + paintOperationHelper(list); } -void LOTContentGroupItem::paintOperationHelper(std::vector &list) +void LOTContentGroupItem::paintOperationHelper( + std::vector &list) { - int curOpCount = list.size(); - for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) { - auto child = *i; - if (auto pathNode = dynamic_cast(child)) { - // the node is a path data node add the paint operation list to it. - pathNode->addPaintOperation(list, curOpCount); - } else if (auto paintNode = dynamic_cast(child)) { - // add it to the paint operation list - list.push_back(paintNode); - } else if (auto groupNode = dynamic_cast(child)) { - // update the groups node with current list - groupNode->paintOperationHelper(list); - } - } - list.erase(list.begin() + curOpCount, list.end()); + int curOpCount = list.size(); + for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) { + auto child = *i; + if (auto pathNode = dynamic_cast(child)) { + // the node is a path data node add the paint operation list to it. + pathNode->addPaintOperation(list, curOpCount); + } else if (auto paintNode = dynamic_cast(child)) { + // add it to the paint operation list + list.push_back(paintNode); + } else if (auto groupNode = + dynamic_cast(child)) { + // update the groups node with current list + groupNode->paintOperationHelper(list); + } + } + list.erase(list.begin() + curOpCount, list.end()); } -void LOTPathDataItem::addPaintOperation(std::vector &list, int externalCount) +void LOTPathDataItem::addPaintOperation(std::vector &list, + int externalCount) { - for(auto paintItem : list) { - bool sameGroup = (externalCount-- > 0) ? false : true; - mNodeList.push_back(std::make_unique()); - mRenderList.push_back(LOTRenderNode(this, paintItem, mNodeList.back().get(), sameGroup)); + for (auto paintItem : list) { + bool sameGroup = (externalCount-- > 0) ? false : true; + mNodeList.push_back(std::make_unique()); + mRenderList.push_back( + LOTRenderNode(this, paintItem, mNodeList.back().get(), sameGroup)); } } void LOTContentGroupItem::processTrimOperation() { - std::vector list; - trimOperationHelper(list); + std::vector list; + trimOperationHelper(list); } void LOTContentGroupItem::trimOperationHelper(std::vector &list) { - int curOpCount = list.size(); - for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) { - auto child = *i; - if (auto pathNode = dynamic_cast(child)) { - // the node is a path data node add the trim operation list to it. - pathNode->addTrimOperation(list); - } else if (auto trimNode = dynamic_cast(child)) { - // add it to the trim operation list - list.push_back(trimNode); - } else if (auto groupNode = dynamic_cast(child)) { - // update the groups node with current list - groupNode->trimOperationHelper(list); - } - } - list.erase(list.begin() + curOpCount, list.end()); + int curOpCount = list.size(); + for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) { + auto child = *i; + if (auto pathNode = dynamic_cast(child)) { + // the node is a path data node add the trim operation list to it. + pathNode->addTrimOperation(list); + } else if (auto trimNode = dynamic_cast(child)) { + // add it to the trim operation list + list.push_back(trimNode); + } else if (auto groupNode = + dynamic_cast(child)) { + // update the groups node with current list + groupNode->trimOperationHelper(list); + } + } + list.erase(list.begin() + curOpCount, list.end()); } void LOTPathDataItem::addTrimOperation(std::vector &list) { - for(auto trimItem : list) { - mTrimNodeRefs.push_back(trimItem); - } + for (auto trimItem : list) { + mTrimNodeRefs.push_back(trimItem); + } } -void LOTPathDataItem::update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) +void LOTPathDataItem::update(int frameNo, const VMatrix &parentMatrix, + float parentAlpha, const DirtyFlag &flag) { - VPath tempPath; + VPath tempPath; - mPathChanged = false; - mCombinedAlpha = parentAlpha; + mPathChanged = false; + mCombinedAlpha = parentAlpha; - // 1. update the local path if needed - if (!(mInit && mStaticPath)) { - mLocalPath = getPath(frameNo); - mInit = true; - mPathChanged = true; - } + // 1. update the local path if needed + if (!(mInit && mStaticPath)) { + mLocalPath = getPath(frameNo); + mInit = true; + mPathChanged = true; + } - tempPath = mLocalPath; + tempPath = mLocalPath; - // 2. apply path operation if needed - if (mTrimNodeRefs.size() > 0) - { - //TODO apply more than one trim path if necessary + // 2. apply path operation if needed + if (mTrimNodeRefs.size() > 0) { + // TODO apply more than one trim path if necessary VPathMesure pm; - float s = mTrimNodeRefs.front()->getStart(frameNo) / 100.0f; - float e = mTrimNodeRefs.front()->getEnd(frameNo) / 100.0f; + float s = mTrimNodeRefs.front()->getStart(frameNo) / 100.0f; + float e = mTrimNodeRefs.front()->getEnd(frameNo) / 100.0f; pm.setOffset(s, e); tempPath = pm.trim(tempPath); mPathChanged = true; - } + } - // 3. compute the final path with parentMatrix + // 3. compute the final path with parentMatrix - if ((flag & DirtyFlagBit::Matrix) || mPathChanged) { - mFinalPath = tempPath; - mFinalPath.transform(parentMatrix); - mPathChanged = true; - } + if ((flag & DirtyFlagBit::Matrix) || mPathChanged) { + mFinalPath = tempPath; + mFinalPath.transform(parentMatrix); + mPathChanged = true; + } - // 2. update the rendernode list - for (const auto &i : mRenderList) { - i.drawable->mFlag = VDrawable::DirtyState::None; - i.paintNodeRef->updateRenderNode(i.pathNodeRef, i.drawable, i.sameGroup); - if (mPathChanged) { - i.drawable->mPath = mFinalPath; - i.drawable->mFlag |= VDrawable::DirtyState::Path; - } - } + // 2. update the rendernode list + for (const auto &i : mRenderList) { + i.drawable->mFlag = VDrawable::DirtyState::None; + i.paintNodeRef->updateRenderNode(i.pathNodeRef, i.drawable, + i.sameGroup); + if (mPathChanged) { + i.drawable->mPath = mFinalPath; + i.drawable->mFlag |= VDrawable::DirtyState::Path; + } + } } void LOTPathDataItem::renderList(std::vector &list) { - for (const auto &i : mRenderList) { - list.push_back(i.drawable); - } + for (const auto &i : mRenderList) { + list.push_back(i.drawable); + } } VPath LOTPathDataItem::path() const { - return mFinalPath; + return mFinalPath; } - -LOTRectItem::LOTRectItem(LOTRectData *data):LOTPathDataItem(data->isStatic()),mData(data) +LOTRectItem::LOTRectItem(LOTRectData *data) + : LOTPathDataItem(data->isStatic()), mData(data) { } VPath LOTRectItem::getPath(int frameNo) { - VPointF pos = mData->mPos.value(frameNo); - VPointF size = mData->mSize.value(frameNo); - float radius = mData->mRound.value(frameNo); - VRectF r(pos.x() - size.x()/2, pos.y() - size.y()/2, size.x(), size.y()); + VPointF pos = mData->mPos.value(frameNo); + VPointF size = mData->mSize.value(frameNo); + float radius = mData->mRound.value(frameNo); + VRectF r(pos.x() - size.x() / 2, pos.y() - size.y() / 2, size.x(), + size.y()); - VPath path; - path.addRoundRect(r, radius, radius, mData->direction()); + VPath path; + path.addRoundRect(r, radius, radius, mData->direction()); - return path; + return path; } -LOTEllipseItem::LOTEllipseItem(LOTEllipseData *data):LOTPathDataItem(data->isStatic()),mData(data) +LOTEllipseItem::LOTEllipseItem(LOTEllipseData *data) + : LOTPathDataItem(data->isStatic()), mData(data) { - } VPath LOTEllipseItem::getPath(int frameNo) { - VPointF pos = mData->mPos.value(frameNo); - VPointF size = mData->mSize.value(frameNo); - VRectF r(pos.x() - size.x()/2, pos.y() - size.y()/2, size.x(), size.y()); + VPointF pos = mData->mPos.value(frameNo); + VPointF size = mData->mSize.value(frameNo); + VRectF r(pos.x() - size.x() / 2, pos.y() - size.y() / 2, size.x(), + size.y()); - VPath path; - path.addOval(r, mData->direction()); + VPath path; + path.addOval(r, mData->direction()); - return path; + return path; } -LOTShapeItem::LOTShapeItem(LOTShapeData *data):LOTPathDataItem(data->isStatic()),mData(data) +LOTShapeItem::LOTShapeItem(LOTShapeData *data) + : LOTPathDataItem(data->isStatic()), mData(data) { - } VPath LOTShapeItem::getPath(int frameNo) @@ -764,90 +768,88 @@ VPath LOTShapeItem::getPath(int frameNo) return mData->mShape.value(frameNo).toPath(); } - -LOTPolystarItem::LOTPolystarItem(LOTPolystarData *data):LOTPathDataItem(data->isStatic()),mData(data) +LOTPolystarItem::LOTPolystarItem(LOTPolystarData *data) + : LOTPathDataItem(data->isStatic()), mData(data) { - } VPath LOTPolystarItem::getPath(int frameNo) { - VPointF pos = mData->mPos.value(frameNo); - float points = mData->mPointCount.value(frameNo); - float innerRadius = mData->mInnerRadius.value(frameNo); - float outerRadius = mData->mOuterRadius.value(frameNo); - float innerRoundness = mData->mInnerRoundness.value(frameNo); - float outerRoundness = mData->mOuterRoundness.value(frameNo); - float rotation = mData->mRotation.value(frameNo); + VPointF pos = mData->mPos.value(frameNo); + float points = mData->mPointCount.value(frameNo); + float innerRadius = mData->mInnerRadius.value(frameNo); + float outerRadius = mData->mOuterRadius.value(frameNo); + float innerRoundness = mData->mInnerRoundness.value(frameNo); + float outerRoundness = mData->mOuterRoundness.value(frameNo); + float rotation = mData->mRotation.value(frameNo); - VPath path; - VMatrix m; + VPath path; + VMatrix m; - if (mData->mType == LOTPolystarData::PolyType::Star) { - path.addPolystar(points, innerRadius, outerRadius, - innerRoundness, outerRoundness, - 0.0, 0.0, 0.0, mData->direction()); - } else { - path.addPolygon(points, outerRadius, outerRoundness, - 0.0, 0.0, 0.0, mData->direction()); - } + if (mData->mType == LOTPolystarData::PolyType::Star) { + path.addPolystar(points, innerRadius, outerRadius, innerRoundness, + outerRoundness, 0.0, 0.0, 0.0, mData->direction()); + } else { + path.addPolygon(points, outerRadius, outerRoundness, 0.0, 0.0, 0.0, + mData->direction()); + } - m.translate(pos.x(), pos.y()).rotate(rotation); - m.rotate(rotation); - path.transform(m); + m.translate(pos.x(), pos.y()).rotate(rotation); + m.rotate(rotation); + path.transform(m); - return path; + return path; } - - /* * PaintData Node handling * */ -void LOTPaintDataItem::update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) +void LOTPaintDataItem::update(int frameNo, const VMatrix &parentMatrix, + float parentAlpha, const DirtyFlag &flag) { - mContentChanged = false; - mParentAlpha = parentAlpha; - mParentMatrix = parentMatrix; - mFlag = flag; - mFrameNo = frameNo; - // 1. update the local content if needed - // if (!(mInit && mStaticContent)) { - mInit = true; - updateContent(frameNo); - mContentChanged = true; - // } + mContentChanged = false; + mParentAlpha = parentAlpha; + mParentMatrix = parentMatrix; + mFlag = flag; + mFrameNo = frameNo; + // 1. update the local content if needed + // if (!(mInit && mStaticContent)) { + mInit = true; + updateContent(frameNo); + mContentChanged = true; + // } } - -LOTFillItem::LOTFillItem(LOTFillData *data):LOTPaintDataItem(data->isStatic()),mData(data) +LOTFillItem::LOTFillItem(LOTFillData *data) + : LOTPaintDataItem(data->isStatic()), mData(data) { } void LOTFillItem::updateContent(int frameNo) { - LottieColor c = mData->mColor.value(frameNo); - float opacity = mData->opacity(frameNo); - mColor = c.toColor(opacity); - mFillRule = mData->fillRule(); + LottieColor c = mData->mColor.value(frameNo); + float opacity = mData->opacity(frameNo); + mColor = c.toColor(opacity); + mFillRule = mData->fillRule(); } -void LOTFillItem::updateRenderNode(LOTPathDataItem *pathNode, VDrawable *drawable, bool sameParent) +void LOTFillItem::updateRenderNode(LOTPathDataItem *pathNode, + VDrawable *drawable, bool sameParent) { VColor color = mColor; if (sameParent) - color.setAlpha(color.a * pathNode->combinedAlpha()); + color.setAlpha(color.a * pathNode->combinedAlpha()); else - color.setAlpha(color.a * parentAlpha() * pathNode->combinedAlpha()); + color.setAlpha(color.a * parentAlpha() * pathNode->combinedAlpha()); VBrush brush(color); drawable->setBrush(brush); drawable->setFillRule(mFillRule); } - -LOTGFillItem::LOTGFillItem(LOTGFillData *data):LOTPaintDataItem(data->isStatic()),mData(data) +LOTGFillItem::LOTGFillItem(LOTGFillData *data) + : LOTPaintDataItem(data->isStatic()), mData(data) { } @@ -858,13 +860,15 @@ void LOTGFillItem::updateContent(int frameNo) mFillRule = mData->fillRule(); } -void LOTGFillItem::updateRenderNode(LOTPathDataItem *pathNode, VDrawable *drawable, bool sameParent) +void LOTGFillItem::updateRenderNode(LOTPathDataItem *pathNode, + VDrawable *drawable, bool sameParent) { drawable->setBrush(VBrush(mGradient.get())); drawable->setFillRule(mFillRule); } -LOTStrokeItem::LOTStrokeItem(LOTStrokeData *data):LOTPaintDataItem(data->isStatic()),mData(data) +LOTStrokeItem::LOTStrokeItem(LOTStrokeData *data) + : LOTPaintDataItem(data->isStatic()), mData(data) { mDashArraySize = 0; } @@ -872,7 +876,7 @@ LOTStrokeItem::LOTStrokeItem(LOTStrokeData *data):LOTPaintDataItem(data->isStati void LOTStrokeItem::updateContent(int frameNo) { LottieColor c = mData->mColor.value(frameNo); - float opacity = mData->opacity(frameNo); + float opacity = mData->opacity(frameNo); mColor = c.toColor(opacity); mCap = mData->capStyle(); mJoin = mData->joinStyle(); @@ -886,33 +890,36 @@ void LOTStrokeItem::updateContent(int frameNo) static float getScale(const VMatrix &matrix) { constexpr float SQRT_2 = 1.41421; - VPointF p1(0,0); - VPointF p2(SQRT_2,SQRT_2); + VPointF p1(0, 0); + VPointF p2(SQRT_2, SQRT_2); p1 = matrix.map(p1); p2 = matrix.map(p2); VPointF final = p2 - p1; - return std::sqrt( final.x() * final.x() + final.y() * final.y()); + return std::sqrt(final.x() * final.x() + final.y() * final.y()); } -void LOTStrokeItem::updateRenderNode(LOTPathDataItem *pathNode, VDrawable *drawable, bool sameParent) +void LOTStrokeItem::updateRenderNode(LOTPathDataItem *pathNode, + VDrawable *drawable, bool sameParent) { VColor color = mColor; if (sameParent) - color.setAlpha(color.a * pathNode->combinedAlpha()); + color.setAlpha(color.a * pathNode->combinedAlpha()); else - color.setAlpha(color.a * parentAlpha() * pathNode->combinedAlpha()); + color.setAlpha(color.a * parentAlpha() * pathNode->combinedAlpha()); VBrush brush(color); drawable->setBrush(brush); - drawable->setStrokeInfo(mCap, mJoin, mMiterLimit, mWidth * getScale(mParentMatrix)); + drawable->setStrokeInfo(mCap, mJoin, mMiterLimit, + mWidth * getScale(mParentMatrix)); if (mDashArraySize) { drawable->setDashInfo(mDashArray, mDashArraySize); } } -LOTGStrokeItem::LOTGStrokeItem(LOTGStrokeData *data):LOTPaintDataItem(data->isStatic()),mData(data) +LOTGStrokeItem::LOTGStrokeItem(LOTGStrokeData *data) + : LOTPaintDataItem(data->isStatic()), mData(data) { mDashArraySize = 0; } @@ -930,37 +937,32 @@ void LOTGStrokeItem::updateContent(int frameNo) } } -void LOTGStrokeItem::updateRenderNode(LOTPathDataItem *pathNode, VDrawable *drawable, bool sameParent) +void LOTGStrokeItem::updateRenderNode(LOTPathDataItem *pathNode, + VDrawable *drawable, bool sameParent) { drawable->setBrush(VBrush(mGradient.get())); - drawable->setStrokeInfo(mCap, mJoin, mMiterLimit, mWidth * getScale(mParentMatrix)); + drawable->setStrokeInfo(mCap, mJoin, mMiterLimit, + mWidth * getScale(mParentMatrix)); if (mDashArraySize) { drawable->setDashInfo(mDashArray, mDashArraySize); } } -LOTTrimItem::LOTTrimItem(LOTTrimData *data):mData(data) -{ -} +LOTTrimItem::LOTTrimItem(LOTTrimData *data) : mData(data) {} -void LOTTrimItem::update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) +void LOTTrimItem::update(int frameNo, const VMatrix &parentMatrix, + float parentAlpha, const DirtyFlag &flag) { } -LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data):mData(data) -{ +LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data) : mData(data) {} -} - -void LOTRepeaterItem::update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) +void LOTRepeaterItem::update(int frameNo, const VMatrix &parentMatrix, + float parentAlpha, const DirtyFlag &flag) { - } -void LOTRepeaterItem::renderList(std::vector &list) -{ - -} +void LOTRepeaterItem::renderList(std::vector &list) {} void LOTDrawable::sync() { @@ -969,9 +971,9 @@ void LOTDrawable::sync() if (mFlag & DirtyState::Path) { const std::vector &elm = mPath.elements(); - const std::vector &pts = mPath.points(); + const std::vector & pts = mPath.points(); const float *ptPtr = reinterpret_cast(pts.data()); - const char *elmPtr = reinterpret_cast(elm.data()); + const char * elmPtr = reinterpret_cast(elm.data()); mCNode.mPath.elmPtr = elmPtr; mCNode.mPath.elmCount = elm.size(); mCNode.mPath.ptPtr = ptPtr; @@ -1060,5 +1062,3 @@ void LOTDrawable::sync() break; } } - - diff --git a/src/lottie/lottieloader.cpp b/src/lottie/lottieloader.cpp index 122dbe2..b97dd68 100644 --- a/src/lottie/lottieloader.cpp +++ b/src/lottie/lottieloader.cpp @@ -1,85 +1,75 @@ #include "lottieloader.h" #include "lottieparser.h" -#include -#include +#include +#include using namespace std; -class LottieFileCache -{ +class LottieFileCache { public: - ~LottieFileCache(); - static LottieFileCache &get() { - static LottieFileCache CACHE; - - return CACHE; - } - std::shared_ptr find(std::string &key); - void add(std::string &key, std::shared_ptr value); -private: - LottieFileCache(){} + ~LottieFileCache(); + static LottieFileCache &get() + { + static LottieFileCache CACHE; + + return CACHE; + } + std::shared_ptr find(std::string &key); + void add(std::string &key, std::shared_ptr value); - std::unordered_map> mHash; +private: + LottieFileCache() {} + std::unordered_map> mHash; }; -LottieFileCache::~LottieFileCache() +LottieFileCache::~LottieFileCache() {} +std::shared_ptr LottieFileCache::find(std::string &key) { - -} -std::shared_ptr -LottieFileCache::find(std::string &key) -{ - auto search = mHash.find(key); - if (search != mHash.end()) { - return search->second; - } else { - return nullptr; - } + auto search = mHash.find(key); + if (search != mHash.end()) { + return search->second; + } else { + return nullptr; + } } -void -LottieFileCache::add(std::string &key, std::shared_ptr value) +void LottieFileCache::add(std::string &key, std::shared_ptr value) { - mHash[key] = value; + mHash[key] = value; } -LottieLoader::LottieLoader() -{ - -} +LottieLoader::LottieLoader() {} bool LottieLoader::load(std::string &path) { - LottieFileCache &fileCache = LottieFileCache::get(); + LottieFileCache &fileCache = LottieFileCache::get(); - mModel = fileCache.find(path); - if (mModel) - return true; + mModel = fileCache.find(path); + if (mModel) return true; - std::ifstream f; - f.open(path); + std::ifstream f; + f.open(path); - if (!f.is_open()) { - vCritical << "failed to open file = " << path.c_str(); - return false; - } else { - std::stringstream buf; - buf << f.rdbuf(); + if (!f.is_open()) { + vCritical << "failed to open file = " << path.c_str(); + return false; + } else { + std::stringstream buf; + buf << f.rdbuf(); - LottieParser parser(const_cast(buf.str().data())); - mModel = parser.model(); - fileCache.add(path, mModel); + LottieParser parser(const_cast(buf.str().data())); + mModel = parser.model(); + fileCache.add(path, mModel); - f.close(); - } + f.close(); + } - return true; + return true; } std::shared_ptr LottieLoader::model() { - return mModel; + return mModel; } - diff --git a/src/lottie/lottiemodel.cpp b/src/lottie/lottiemodel.cpp index 17cbb00..7015749 100644 --- a/src/lottie/lottiemodel.cpp +++ b/src/lottie/lottiemodel.cpp @@ -1,13 +1,10 @@ #include "lottiemodel.h" -#include -#include +#include +#include - - -class LottieRepeaterProcesser : public LOTDataVisitor -{ +class LottieRepeaterProcesser : public LOTDataVisitor { public: - LottieRepeaterProcesser():mRepeaterFound(false){} + LottieRepeaterProcesser() : mRepeaterFound(false) {} void visit(LOTCompositionData *obj) {} void visit(LOTLayerData *obj) {} void visit(LOTTransformData *) {} @@ -16,24 +13,26 @@ public: void visit(LOTRectData *) {} void visit(LOTEllipseData *) {} void visit(LOTTrimData *) {} - void visit(LOTRepeaterData *) { mRepeaterFound = true;} + void visit(LOTRepeaterData *) { mRepeaterFound = true; } void visit(LOTFillData *) {} void visit(LOTStrokeData *) {} void visit(LOTPolystarData *) {} - void visitChildren(LOTGroupData *obj) { - for(auto child :obj->mChildren) { + void visitChildren(LOTGroupData *obj) + { + for (auto child : obj->mChildren) { child.get()->accept(this); if (mRepeaterFound) { - LOTRepeaterData *repeater = static_cast(child.get()); - std::shared_ptr sharedShapeGroup= std::make_shared(); + LOTRepeaterData *repeater = + static_cast(child.get()); + std::shared_ptr sharedShapeGroup = + std::make_shared(); LOTShapeGroupData *shapeGroup = sharedShapeGroup.get(); repeater->mChildren.push_back(sharedShapeGroup); // copy all the child of the object till repeater and // move that in to a group and then add that group to // the repeater object. - for(auto cpChild :obj->mChildren) { - if (cpChild == child) - break; + for (auto cpChild : obj->mChildren) { + if (cpChild == child) break; // there shouldn't be any trim object left in the child list if (cpChild.get()->type() == LOTData::Type::Trim) { assert(0); @@ -44,102 +43,113 @@ public: } } } + public: bool mRepeaterFound; }; -class LottiePathOperationProcesser : public LOTDataVisitor -{ +class LottiePathOperationProcesser : public LOTDataVisitor { public: - LottiePathOperationProcesser():mPathOperator(false), mPathNode(false){} + LottiePathOperationProcesser() : mPathOperator(false), mPathNode(false) {} void visit(LOTCompositionData *obj) {} void visit(LOTLayerData *obj) {} void visit(LOTTransformData *) {} void visit(LOTShapeGroupData *obj) {} - void visit(LOTShapeData *) {mPathNode = true;} - void visit(LOTRectData *) {mPathNode = true;} - void visit(LOTEllipseData *) { mPathNode = true;} - void visit(LOTTrimData *) { mPathOperator = true;} + void visit(LOTShapeData *) { mPathNode = true; } + void visit(LOTRectData *) { mPathNode = true; } + void visit(LOTEllipseData *) { mPathNode = true; } + void visit(LOTTrimData *) { mPathOperator = true; } void visit(LOTRepeaterData *) {} void visit(LOTFillData *) {} void visit(LOTStrokeData *) {} - void visit(LOTPolystarData *) { mPathNode = true;} - void visitChildren(LOTGroupData *obj) { + void visit(LOTPolystarData *) { mPathNode = true; } + void visitChildren(LOTGroupData *obj) + { int curOpCount = mPathOperationList.size(); mPathOperator = false; mPathNode = false; - for (auto i = obj->mChildren.rbegin(); i != obj->mChildren.rend(); ++i) { + for (auto i = obj->mChildren.rbegin(); i != obj->mChildren.rend(); + ++i) { auto child = *i; child.get()->accept(this); if (mPathOperator) { mPathOperationList.push_back(child); - //obj->mChildren.erase(std::next(i).base()); + // obj->mChildren.erase(std::next(i).base()); } if (mPathNode) { - updatePathObject(static_cast(child.get())); + updatePathObject(static_cast(child.get())); } mPathOperator = false; mPathNode = false; } - mPathOperationList.erase(mPathOperationList.begin() + curOpCount, mPathOperationList.end()); + mPathOperationList.erase(mPathOperationList.begin() + curOpCount, + mPathOperationList.end()); } - void updatePathObject(LOTPath *drawable) { - for (auto i = mPathOperationList.rbegin(); i != mPathOperationList.rend(); ++i) { + void updatePathObject(LOTPath *drawable) + { + for (auto i = mPathOperationList.rbegin(); + i != mPathOperationList.rend(); ++i) { drawable->mPathOperations.push_back(*i); } } + public: - bool mPathOperator; - bool mPathNode; + bool mPathOperator; + bool mPathNode; std::vector> mPathOperationList; }; -class LottiePaintOperationProcesser : public LOTDataVisitor -{ +class LottiePaintOperationProcesser : public LOTDataVisitor { public: - LottiePaintOperationProcesser():mPaintOperator(false), mPathNode(false){} + LottiePaintOperationProcesser() : mPaintOperator(false), mPathNode(false) {} void visit(LOTCompositionData *obj) {} void visit(LOTLayerData *obj) {} void visit(LOTTransformData *) {} void visit(LOTShapeGroupData *obj) {} - void visit(LOTShapeData *) {mPathNode = true;} - void visit(LOTRectData *) {mPathNode = true;} - void visit(LOTEllipseData *) { mPathNode = true;} + void visit(LOTShapeData *) { mPathNode = true; } + void visit(LOTRectData *) { mPathNode = true; } + void visit(LOTEllipseData *) { mPathNode = true; } void visit(LOTTrimData *) {} void visit(LOTRepeaterData *) {} - void visit(LOTFillData *) { mPaintOperator = true;} - void visit(LOTStrokeData *) { mPaintOperator = true;} - void visit(LOTPolystarData *) { mPathNode = true;} - void visitChildren(LOTGroupData *obj) { + void visit(LOTFillData *) { mPaintOperator = true; } + void visit(LOTStrokeData *) { mPaintOperator = true; } + void visit(LOTPolystarData *) { mPathNode = true; } + void visitChildren(LOTGroupData *obj) + { int curOpCount = mPaintOperationList.size(); mPaintOperator = false; mPathNode = false; - for (auto i = obj->mChildren.rbegin(); i != obj->mChildren.rend(); ++i) { + for (auto i = obj->mChildren.rbegin(); i != obj->mChildren.rend(); + ++i) { auto child = *i; child.get()->accept(this); if (mPaintOperator) { mPaintOperationList.push_back(child); - //obj->mChildren.erase(std::next(i).base()); + // obj->mChildren.erase(std::next(i).base()); } if (mPathNode) { - // put it in the list - updatePathObject(static_cast(child.get())); + // put it in the list + updatePathObject(static_cast(child.get())); } mPaintOperator = false; mPathNode = false; } - mPaintOperationList.erase(mPaintOperationList.begin() + curOpCount, mPaintOperationList.end()); + mPaintOperationList.erase(mPaintOperationList.begin() + curOpCount, + mPaintOperationList.end()); } - void updatePathObject(LOTPath *drawable) { - for (auto i = mPaintOperationList.begin(); i != mPaintOperationList.end(); ++i) { + void updatePathObject(LOTPath *drawable) + { + for (auto i = mPaintOperationList.begin(); + i != mPaintOperationList.end(); ++i) { drawable->mPaintOperations.push_back(*i); } } + public: - bool mPaintOperator; - bool mPathNode; + bool mPaintOperator; + bool mPathNode; std::vector> mPaintOperationList; }; @@ -161,7 +171,6 @@ void LOTCompositionData::processPaintOperatorObjects() accept(&visitor); } - VMatrix LOTTransformData::matrix(int frameNo) const { if (mStaticMatrix) @@ -172,7 +181,7 @@ VMatrix LOTTransformData::matrix(int frameNo) const float LOTTransformData::opacity(int frameNo) const { - return mOpacity.value(frameNo)/100.f; + return mOpacity.value(frameNo) / 100.f; } void LOTTransformData::cacheMatrix() @@ -183,10 +192,10 @@ void LOTTransformData::cacheMatrix() VMatrix LOTTransformData::computeMatrix(int frameNo) const { VMatrix m; - m.translate(mPosition.value(frameNo)). - rotate(mRotation.value(frameNo)). - scale(mScale.value(frameNo)/100.f). - translate(-mAnchor.value(frameNo)); + m.translate(mPosition.value(frameNo)) + .rotate(mRotation.value(frameNo)) + .scale(mScale.value(frameNo) / 100.f) + .translate(-mAnchor.value(frameNo)); return m; } @@ -199,14 +208,14 @@ int LOTStrokeData::getDashInfo(int frameNo, float *array) const array[i] = mDash.mDashArray[i].value(frameNo); } return mDash.mDashCount; - } else { // even case when last gap info is not provided. + } else { // even case when last gap info is not provided. int i; - for (i = 0; i < mDash.mDashCount-1 ; i++) { + for (i = 0; i < mDash.mDashCount - 1; i++) { array[i] = mDash.mDashArray[i].value(frameNo); } - array[i] = array[i-1]; - array[i+1] = mDash.mDashArray[i].value(frameNo); - return mDash.mDashCount+1; + array[i] = array[i - 1]; + array[i + 1] = mDash.mDashArray[i].value(frameNo); + return mDash.mDashCount + 1; } } @@ -219,14 +228,14 @@ int LOTGStrokeData::getDashInfo(int frameNo, float *array) const array[i] = mDash.mDashArray[i].value(frameNo); } return mDash.mDashCount; - } else { // even case when last gap info is not provided. + } else { // even case when last gap info is not provided. int i; - for (i = 0; i < mDash.mDashCount-1 ; i++) { + for (i = 0; i < mDash.mDashCount - 1; i++) { array[i] = mDash.mDashArray[i].value(frameNo); } - array[i] = array[i-1]; - array[i+1] = mDash.mDashArray[i].value(frameNo); - return mDash.mDashCount+1; + array[i] = array[i - 1]; + array[i + 1] = mDash.mDashArray[i].value(frameNo); + return mDash.mDashCount + 1; } } @@ -253,49 +262,57 @@ int LOTGStrokeData::getDashInfo(int frameNo, float *array) const void LOTGradient::populate(VGradientStops &stops, int frameNo) { LottieGradient gradData = mGradient.value(frameNo); - int size = gradData.mGradient.size(); - float *ptr = gradData.mGradient.data(); - int colorPoints = mColorPoints; - if (colorPoints == -1 ) { // for legacy bodymovin (ref: lottie-android) + int size = gradData.mGradient.size(); + float * ptr = gradData.mGradient.data(); + int colorPoints = mColorPoints; + if (colorPoints == -1) { // for legacy bodymovin (ref: lottie-android) colorPoints = size / 4; } - int opacityArraySize = size - colorPoints * 4; + int opacityArraySize = size - colorPoints * 4; float *opacityPtr = ptr + (colorPoints * 4); stops.clear(); int j = 0; - for (int i = 0; i < colorPoints ; i++) { - float colorStop = ptr[0]; + for (int i = 0; i < colorPoints; i++) { + float colorStop = ptr[0]; LottieColor color = LottieColor(ptr[1], ptr[2], ptr[3]); if (opacityArraySize) { if (j == opacityArraySize) { // already reached the end - float stop1 = opacityPtr[j-4]; - float op1 = opacityPtr[j-3]; - float stop2 = opacityPtr[j-2]; - float op2 = opacityPtr[j-1]; + float stop1 = opacityPtr[j - 4]; + float op1 = opacityPtr[j - 3]; + float stop2 = opacityPtr[j - 2]; + float op2 = opacityPtr[j - 1]; if (colorStop > stop2) { - stops.push_back(std::make_pair(colorStop, color.toColor(op2))); + stops.push_back( + std::make_pair(colorStop, color.toColor(op2))); } else { float progress = (colorStop - stop1) / (stop2 - stop1); float opacity = op1 + progress * (op2 - op1); - stops.push_back(std::make_pair(colorStop, color.toColor(opacity))); + stops.push_back( + std::make_pair(colorStop, color.toColor(opacity))); } continue; } - for (; j < opacityArraySize ; j += 2) { + for (; j < opacityArraySize; j += 2) { float opacityStop = opacityPtr[j]; if (opacityStop < colorStop) { // add a color using opacity stop - stops.push_back(std::make_pair(opacityStop, color.toColor(opacityPtr[j+1]))); + stops.push_back(std::make_pair( + opacityStop, color.toColor(opacityPtr[j + 1]))); continue; } // add a color using color stop if (j == 0) { - stops.push_back(std::make_pair(colorStop, color.toColor(opacityPtr[j+1]))); + stops.push_back(std::make_pair( + colorStop, color.toColor(opacityPtr[j + 1]))); } else { - float progress = (colorStop - opacityPtr[j-2]) / (opacityPtr[j] - opacityPtr[j-2]); - float opacity = opacityPtr[j-1] + progress * (opacityPtr[j+1] - opacityPtr[j-1]); - stops.push_back(std::make_pair(colorStop, color.toColor(opacity))); + float progress = (colorStop - opacityPtr[j - 2]) / + (opacityPtr[j] - opacityPtr[j - 2]); + float opacity = + opacityPtr[j - 1] + + progress * (opacityPtr[j + 1] - opacityPtr[j - 1]); + stops.push_back( + std::make_pair(colorStop, color.toColor(opacity))); } j += 2; break; @@ -312,9 +329,9 @@ void LOTGradient::update(std::unique_ptr &grad, int frameNo) bool init = false; if (!grad) { if (mGradientType == 1) - grad = std::make_unique(0,0,0,0); + grad = std::make_unique(0, 0, 0, 0); else - grad = std::make_unique(0,0,0,0,0,0); + grad = std::make_unique(0, 0, 0, 0, 0, 0); grad->mSpread = VGradient::Spread::Pad; init = true; } @@ -323,39 +340,41 @@ void LOTGradient::update(std::unique_ptr &grad, int frameNo) populate(grad->mStops, frameNo); } - if (mGradientType == 1) { //linear gradient + if (mGradientType == 1) { // linear gradient VPointF start = mStartPoint.value(frameNo); VPointF end = mEndPoint.value(frameNo); grad->linear.x1 = start.x(); grad->linear.y1 = start.y(); grad->linear.x2 = end.x(); grad->linear.y2 = end.y(); - } else { // radial gradient + } else { // radial gradient VPointF start = mStartPoint.value(frameNo); VPointF end = mEndPoint.value(frameNo); grad->radial.cx = start.x(); grad->radial.cy = start.y(); - grad->radial.cradius = vLineLength(start.x(), start.y(), end.x(), end.y()); + grad->radial.cradius = + vLineLength(start.x(), start.y(), end.x(), end.y()); /* - * Focal point is the point lives in highlight length distance from center along the - * line (start, end) and rotated by highlight angle. - * below calculation first finds the quadrant(angle) on which the point lives by applying - * inverse slope formula then adds the rotation angle to find the final angle. - * then point is retrived using circle equation of center, angle and distance. + * Focal point is the point lives in highlight length distance from + * center along the line (start, end) and rotated by highlight angle. + * below calculation first finds the quadrant(angle) on which the point + * lives by applying inverse slope formula then adds the rotation angle + * to find the final angle. then point is retrived using circle equation + * of center, angle and distance. */ - float progress = mHighlightLength.value(frameNo)/100.0f; + float progress = mHighlightLength.value(frameNo) / 100.0f; if (vCompare(progress, 1.0f)) progress = 0.99f; float dy = end.y() - start.y(); float dx = end.x() - start.x(); - float slope = (dx == 0) ? dy * INFINITY : dy/dx; + float slope = (dx == 0) ? dy * INFINITY : dy / dx; float startAngleRad = std::atan(slope); - int highlightAngle = mHighlightAngle.value(frameNo); - float angle = startAngleRad + (highlightAngle * M_PI/180.0f); - grad->radial.fx = grad->radial.cx + std::cos(angle) * progress * grad->radial.cradius; - grad->radial.fy = grad->radial.cy + std::sin(angle) * progress * grad->radial.cradius; + int highlightAngle = mHighlightAngle.value(frameNo); + float angle = startAngleRad + (highlightAngle * M_PI / 180.0f); + grad->radial.fx = + grad->radial.cx + std::cos(angle) * progress * grad->radial.cradius; + grad->radial.fy = + grad->radial.cy + std::sin(angle) * progress * grad->radial.cradius; // Lottie dosen't have any focal radius concept. grad->radial.fradius = 0; } } - - diff --git a/src/lottie/lottieparser.cpp b/src/lottie/lottieparser.cpp index 3eede42..bcdc213 100644 --- a/src/lottie/lottieparser.cpp +++ b/src/lottie/lottieparser.cpp @@ -8,37 +8,36 @@ // callbacks. Instead, we retrieve values from the JSON stream by calling // GetInt(), GetDouble(), GetString() and GetBool(), traverse into structures // by calling EnterObject() and EnterArray(), and skip over unwanted data by -// calling SkipValue(). As we know the lottie file structure this way will be the efficient way -// of parsing the file. +// calling SkipValue(). As we know the lottie file structure this way will be +// the efficient way of parsing the file. // -// If you aren't sure of what's next in the JSON data, you can use PeekType() and -// PeekValue() to look ahead to the next object before reading it. +// If you aren't sure of what's next in the JSON data, you can use PeekType() +// and PeekValue() to look ahead to the next object before reading it. // -// If you call the wrong retrieval method--e.g. GetInt when the next JSON token is -// not an int, EnterObject or EnterArray when there isn't actually an object or array -// to read--the stream parsing will end immediately and no more data will be delivered. +// If you call the wrong retrieval method--e.g. GetInt when the next JSON token +// is not an int, EnterObject or EnterArray when there isn't actually an object +// or array to read--the stream parsing will end immediately and no more data +// will be delivered. // -// After calling EnterObject, you retrieve keys via NextObjectKey() and values via -// the normal getters. When NextObjectKey() returns null, you have exited the -// object, or you can call SkipObject() to skip to the end of the object -// immediately. If you fetch the entire object (i.e. NextObjectKey() returned null), -// you should not call SkipObject(). +// After calling EnterObject, you retrieve keys via NextObjectKey() and values +// via the normal getters. When NextObjectKey() returns null, you have exited +// the object, or you can call SkipObject() to skip to the end of the object +// immediately. If you fetch the entire object (i.e. NextObjectKey() returned +// null), you should not call SkipObject(). // -// After calling EnterArray(), you must alternate between calling NextArrayValue() -// to see if the array has more data, and then retrieving values via the normal -// getters. You can call SkipArray() to skip to the end of the array immediately. -// If you fetch the entire array (i.e. NextArrayValue() returned null), -// you should not call SkipArray(). +// After calling EnterArray(), you must alternate between calling +// NextArrayValue() to see if the array has more data, and then retrieving +// values via the normal getters. You can call SkipArray() to skip to the end of +// the array immediately. If you fetch the entire array (i.e. NextArrayValue() +// returned null), you should not call SkipArray(). // -// This parser uses in-situ strings, so the JSON buffer will be altered during the -// parse. +// This parser uses in-situ strings, so the JSON buffer will be altered during +// the parse. - -#include "rapidjson/document.h" #include #include "lottiemodel.h" -#include"velapsedtimer.h" - +#include "rapidjson/document.h" +#include "velapsedtimer.h" RAPIDJSON_DIAG_PUSH #ifdef __GNUC__ @@ -49,23 +48,84 @@ using namespace rapidjson; class LookaheadParserHandler { public: - bool Null() { st_ = kHasNull; v_.SetNull(); return true; } - bool Bool(bool b) { st_ = kHasBool; v_.SetBool(b); return true; } - bool Int(int i) { st_ = kHasNumber; v_.SetInt(i); return true; } - bool Uint(unsigned u) { st_ = kHasNumber; v_.SetUint(u); return true; } - bool Int64(int64_t i) { st_ = kHasNumber; v_.SetInt64(i); return true; } - bool Uint64(uint64_t u) { st_ = kHasNumber; v_.SetUint64(u); return true; } - bool Double(double d) { st_ = kHasNumber; v_.SetDouble(d); return true; } - bool RawNumber(const char*, SizeType, bool) { return false; } - bool String(const char* str, SizeType length, bool) { st_ = kHasString; v_.SetString(str, length); return true; } - bool StartObject() { st_ = kEnteringObject; return true; } - bool Key(const char* str, SizeType length, bool) { st_ = kHasKey; v_.SetString(str, length); return true; } - bool EndObject(SizeType) { st_ = kExitingObject; return true; } - bool StartArray() { st_ = kEnteringArray; return true; } - bool EndArray(SizeType) { st_ = kExitingArray; return true; } + bool Null() + { + st_ = kHasNull; + v_.SetNull(); + return true; + } + bool Bool(bool b) + { + st_ = kHasBool; + v_.SetBool(b); + return true; + } + bool Int(int i) + { + st_ = kHasNumber; + v_.SetInt(i); + return true; + } + bool Uint(unsigned u) + { + st_ = kHasNumber; + v_.SetUint(u); + return true; + } + bool Int64(int64_t i) + { + st_ = kHasNumber; + v_.SetInt64(i); + return true; + } + bool Uint64(uint64_t u) + { + st_ = kHasNumber; + v_.SetUint64(u); + return true; + } + bool Double(double d) + { + st_ = kHasNumber; + v_.SetDouble(d); + return true; + } + bool RawNumber(const char *, SizeType, bool) { return false; } + bool String(const char *str, SizeType length, bool) + { + st_ = kHasString; + v_.SetString(str, length); + return true; + } + bool StartObject() + { + st_ = kEnteringObject; + return true; + } + bool Key(const char *str, SizeType length, bool) + { + st_ = kHasKey; + v_.SetString(str, length); + return true; + } + bool EndObject(SizeType) + { + st_ = kExitingObject; + return true; + } + bool StartArray() + { + st_ = kEnteringArray; + return true; + } + bool EndArray(SizeType) + { + st_ = kExitingArray; + return true; + } protected: - LookaheadParserHandler(char* str); + LookaheadParserHandler(char *str); void ParseNext(); protected: @@ -83,93 +143,95 @@ protected: kExitingArray }; - Value v_; + Value v_; LookaheadParsingState st_; - Reader r_; - InsituStringStream ss_; + Reader r_; + InsituStringStream ss_; static const int parseFlags = kParseDefaultFlags | kParseInsituFlag; }; - class LottieParserImpl : protected LookaheadParserHandler { public: - LottieParserImpl(char* str) : LookaheadParserHandler(str) {} + LottieParserImpl(char *str) : LookaheadParserHandler(str) {} public: - bool EnterObject(); - bool EnterArray(); - const char* NextObjectKey(); - bool NextArrayValue(); - int GetInt(); - double GetDouble(); - const char* GetString(); - bool GetBool(); - void GetNull(); - - void SkipObject(); - void SkipArray(); - void SkipValue(); - Value* PeekValue(); - int PeekType(); // returns a rapidjson::Type, or -1 for no value (at end of object/array) + bool EnterObject(); + bool EnterArray(); + const char *NextObjectKey(); + bool NextArrayValue(); + int GetInt(); + double GetDouble(); + const char *GetString(); + bool GetBool(); + void GetNull(); + + void SkipObject(); + void SkipArray(); + void SkipValue(); + Value *PeekValue(); + int PeekType(); // returns a rapidjson::Type, or -1 for no value (at end of + // object/array) bool IsValid() { return st_ != kError; } - void Skip(const char *key); - VRect getRect(); - LottieBlendMode getBlendMode(); - CapStyle getLineCap(); - JoinStyle getLineJoin(); - FillRule getFillRule(); + void Skip(const char *key); + VRect getRect(); + LottieBlendMode getBlendMode(); + CapStyle getLineCap(); + JoinStyle getLineJoin(); + FillRule getFillRule(); LOTTrimData::TrimType getTrimType(); - MatteType getMatteType(); - LayerType getLayerType(); - - std::shared_ptr composition() const {return mComposition;} - void parseComposition(); - void parseAssets(LOTCompositionData *comp); - std::shared_ptr parseAsset(); - void parseLayers(LOTCompositionData *comp); - std::shared_ptr parseLayer(); - void parseMaskProperty(LOTLayerData *layer); - void parseShapesAttr(LOTLayerData *layer); - void parseObject(LOTGroupData *parent); - std::shared_ptr parseMaskObject(); - std::shared_ptr parseObjectTypeAttr(); - std::shared_ptr parseGroupObject(); - std::shared_ptr parseRectObject(); - std::shared_ptr parseEllipseObject(); - std::shared_ptr parseShapeObject(); - std::shared_ptr parsePolystarObject(); + MatteType getMatteType(); + LayerType getLayerType(); + + std::shared_ptr composition() const + { + return mComposition; + } + void parseComposition(); + void parseAssets(LOTCompositionData *comp); + std::shared_ptr parseAsset(); + void parseLayers(LOTCompositionData *comp); + std::shared_ptr parseLayer(); + void parseMaskProperty(LOTLayerData *layer); + void parseShapesAttr(LOTLayerData *layer); + void parseObject(LOTGroupData *parent); + std::shared_ptr parseMaskObject(); + std::shared_ptr parseObjectTypeAttr(); + std::shared_ptr parseGroupObject(); + std::shared_ptr parseRectObject(); + std::shared_ptr parseEllipseObject(); + std::shared_ptr parseShapeObject(); + std::shared_ptr parsePolystarObject(); std::shared_ptr parseTransformObject(); - std::shared_ptr parseFillObject(); - std::shared_ptr parseGFillObject(); - std::shared_ptr parseStrokeObject(); - std::shared_ptr parseGStrokeObject(); - std::shared_ptr parseTrimObject(); - std::shared_ptr parseReapeaterObject(); - + std::shared_ptr parseFillObject(); + std::shared_ptr parseGFillObject(); + std::shared_ptr parseStrokeObject(); + std::shared_ptr parseGStrokeObject(); + std::shared_ptr parseTrimObject(); + std::shared_ptr parseReapeaterObject(); void parseGradientProperty(LOTGradient *gradient, const char *key); VPointF parseInperpolatorPoint(); - void parseArrayValue(VPointF &pt); - void parseArrayValue(LottieColor &pt); - void parseArrayValue(float &val); - void parseArrayValue(int &val); - void parseArrayValue(LottieGradient &gradient); - void getValue(VPointF &val); - void getValue(float &val); - void getValue(LottieColor &val); - void getValue(int &val); - void getValue(LottieShapeData &shape); - void getValue(LottieGradient &gradient); - template - bool parseKeyFrameValue(const char* key, LOTKeyFrameValue &value); - template + void parseArrayValue(VPointF &pt); + void parseArrayValue(LottieColor &pt); + void parseArrayValue(float &val); + void parseArrayValue(int &val); + void parseArrayValue(LottieGradient &gradient); + void getValue(VPointF &val); + void getValue(float &val); + void getValue(LottieColor &val); + void getValue(int &val); + void getValue(LottieShapeData &shape); + void getValue(LottieGradient &gradient); + template + bool parseKeyFrameValue(const char *key, LOTKeyFrameValue &value); + template void parseKeyFrame(LOTAnimInfo &obj); - template + template void parseProperty(LOTAnimatable &obj); void parseShapeKeyFrame(LOTAnimInfo &obj); @@ -180,35 +242,39 @@ public: LottieColor toColor(const char *str); void resolveLayerRefs(); + protected: - std::shared_ptr mComposition; - LOTCompositionData *compRef; - LOTLayerData *curLayerRef; - std::vector> mLayersToUpdate; - void SkipOut(int depth); + std::shared_ptr mComposition; + LOTCompositionData * compRef; + LOTLayerData * curLayerRef; + std::vector> mLayersToUpdate; + void SkipOut(int depth); }; -LookaheadParserHandler::LookaheadParserHandler(char* str) : v_(), st_(kInit), r_(), ss_(str) { +LookaheadParserHandler::LookaheadParserHandler(char *str) + : v_(), st_(kInit), r_(), ss_(str) +{ r_.IterativeParseInit(); ParseNext(); } -void LookaheadParserHandler::ParseNext() { +void LookaheadParserHandler::ParseNext() +{ if (r_.HasParseError()) { st_ = kError; return; } if (!r_.IterativeParseNext(ss_, *this)) { - vCritical<<"Lottie file parsing error"; + vCritical << "Lottie file parsing error"; RAPIDJSON_ASSERT(0); } } - -bool LottieParserImpl::EnterObject() { +bool LottieParserImpl::EnterObject() +{ if (st_ != kEnteringObject) { - st_ = kError; + st_ = kError; RAPIDJSON_ASSERT(false); return false; } @@ -217,9 +283,10 @@ bool LottieParserImpl::EnterObject() { return true; } -bool LottieParserImpl::EnterArray() { +bool LottieParserImpl::EnterArray() +{ if (st_ != kEnteringArray) { - st_ = kError; + st_ = kError; RAPIDJSON_ASSERT(false); return false; } @@ -228,9 +295,10 @@ bool LottieParserImpl::EnterArray() { return true; } -const char* LottieParserImpl::NextObjectKey() { +const char *LottieParserImpl::NextObjectKey() +{ if (st_ == kHasKey) { - const char* result = v_.GetString(); + const char *result = v_.GetString(); ParseNext(); return result; } @@ -241,10 +309,10 @@ const char* LottieParserImpl::NextObjectKey() { * object we can call multiple time NextObjectKey() while exiting the object * so ignore those and don't put parser in the error state. * */ - if (st_ == kExitingArray || st_ == kEnteringObject ) { -// #ifdef DEBUG_PARSER -// vDebug<<"Object: Exiting nested loop"; -// #endif + if (st_ == kExitingArray || st_ == kEnteringObject) { + // #ifdef DEBUG_PARSER + // vDebug<<"Object: Exiting nested loop"; + // #endif return 0; } @@ -258,7 +326,8 @@ const char* LottieParserImpl::NextObjectKey() { return 0; } -bool LottieParserImpl::NextArrayValue() { +bool LottieParserImpl::NextArrayValue() +{ if (st_ == kExitingArray) { ParseNext(); return false; @@ -268,13 +337,12 @@ bool LottieParserImpl::NextArrayValue() { * same as NextObjectKey() */ if (st_ == kExitingObject) { -// #ifdef DEBUG_PARSER -// vDebug<<"Array: Exiting nested loop"; -// #endif + // #ifdef DEBUG_PARSER + // vDebug<<"Array: Exiting nested loop"; + // #endif return 0; } - if (st_ == kError || st_ == kHasKey) { RAPIDJSON_ASSERT(false); st_ = kError; @@ -284,7 +352,8 @@ bool LottieParserImpl::NextArrayValue() { return true; } -int LottieParserImpl::GetInt() { +int LottieParserImpl::GetInt() +{ if (st_ != kHasNumber || !v_.IsInt()) { st_ = kError; RAPIDJSON_ASSERT(false); @@ -296,9 +365,10 @@ int LottieParserImpl::GetInt() { return result; } -double LottieParserImpl::GetDouble() { +double LottieParserImpl::GetDouble() +{ if (st_ != kHasNumber) { - st_ = kError; + st_ = kError; RAPIDJSON_ASSERT(false); return 0.; } @@ -308,9 +378,10 @@ double LottieParserImpl::GetDouble() { return result; } -bool LottieParserImpl::GetBool() { +bool LottieParserImpl::GetBool() +{ if (st_ != kHasBool) { - st_ = kError; + st_ = kError; RAPIDJSON_ASSERT(false); return false; } @@ -320,58 +391,62 @@ bool LottieParserImpl::GetBool() { return result; } -void LottieParserImpl::GetNull() { +void LottieParserImpl::GetNull() +{ if (st_ != kHasNull) { - st_ = kError; + st_ = kError; return; } ParseNext(); } -const char* LottieParserImpl::GetString() { +const char *LottieParserImpl::GetString() +{ if (st_ != kHasString) { - st_ = kError; + st_ = kError; RAPIDJSON_ASSERT(false); return 0; } - const char* result = v_.GetString(); + const char *result = v_.GetString(); ParseNext(); return result; } -void LottieParserImpl::SkipOut(int depth) { +void LottieParserImpl::SkipOut(int depth) +{ do { if (st_ == kEnteringArray || st_ == kEnteringObject) { ++depth; - } - else if (st_ == kExitingArray || st_ == kExitingObject) { + } else if (st_ == kExitingArray || st_ == kExitingObject) { --depth; - } - else if (st_ == kError) { + } else if (st_ == kError) { RAPIDJSON_ASSERT(false); return; } ParseNext(); - } - while (depth > 0); + } while (depth > 0); } -void LottieParserImpl::SkipValue() { +void LottieParserImpl::SkipValue() +{ SkipOut(0); } -void LottieParserImpl::SkipArray() { +void LottieParserImpl::SkipArray() +{ SkipOut(1); } -void LottieParserImpl::SkipObject() { +void LottieParserImpl::SkipObject() +{ SkipOut(1); } -Value* LottieParserImpl::PeekValue() { +Value *LottieParserImpl::PeekValue() +{ if (st_ >= kHasNull && st_ <= kHasKey) { return &v_; } @@ -379,7 +454,8 @@ Value* LottieParserImpl::PeekValue() { return 0; } -int LottieParserImpl::PeekType() { +int LottieParserImpl::PeekType() +{ if (st_ >= kHasNull && st_ <= kHasKey) { return v_.GetType(); } @@ -408,8 +484,7 @@ void LottieParserImpl::Skip(const char *key) } } -LottieBlendMode -LottieParserImpl::getBlendMode() +LottieBlendMode LottieParserImpl::getBlendMode() { RAPIDJSON_ASSERT(PeekType() == kNumberType); LottieBlendMode mode = LottieBlendMode::Normal; @@ -434,7 +509,7 @@ VRect LottieParserImpl::getRect() VRect r; RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "l")) { RAPIDJSON_ASSERT(PeekType() == kNumberType); r.setLeft(GetInt()); @@ -456,25 +531,24 @@ VRect LottieParserImpl::getRect() void LottieParserImpl::resolveLayerRefs() { - for(auto i : mLayersToUpdate) { + for (auto i : mLayersToUpdate) { LOTLayerData *layer = i.get(); - auto search = compRef->mAssets.find(layer->mPreCompRefId); + auto search = compRef->mAssets.find(layer->mPreCompRefId); if (search != compRef->mAssets.end()) { - layer->mChildren = search->second.get()->mLayers; - } + layer->mChildren = search->second.get()->mLayers; + } } } - -void -LottieParserImpl::parseComposition() +void LottieParserImpl::parseComposition() { RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); - std::shared_ptr sharedComposition = std::make_shared(); + std::shared_ptr sharedComposition = + std::make_shared(); LOTCompositionData *comp = sharedComposition.get(); compRef = comp; - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "v")) { RAPIDJSON_ASSERT(PeekType() == kStringType); comp->mVersion = std::string(GetString()); @@ -499,7 +573,7 @@ LottieParserImpl::parseComposition() parseLayers(comp); } else { #ifdef DEBUG_PARSER - vWarning<<"Composition Attribute Skipped : "<mAssets[asset->mRefId] = asset; } // update the precomp layers with the actual layer object - } /* * https://github.com/airbnb/lottie-web/blob/master/docs/json/layers/shape.json * */ -std::shared_ptr -LottieParserImpl::parseAsset() +std::shared_ptr LottieParserImpl::parseAsset() { RAPIDJSON_ASSERT(PeekType() == kObjectType); std::shared_ptr sharedAsset = std::make_shared(); - LOTAsset *asset = sharedAsset.get(); + LOTAsset * asset = sharedAsset.get(); EnterObject(); - while (const char* key = NextObjectKey()) { - if (0 == strcmp(key, "ty")) { /* Type of layer: Shape. Value 4.*/ + while (const char *key = NextObjectKey()) { + if (0 == strcmp(key, "ty")) { /* Type of layer: Shape. Value 4.*/ RAPIDJSON_ASSERT(PeekType() == kNumberType); asset->mAssetType = GetInt(); - } else if (0 == strcmp(key, "id")) { /* reference id*/ + } else if (0 == strcmp(key, "id")) { /* reference id*/ RAPIDJSON_ASSERT(PeekType() == kStringType); asset->mRefId = std::string(GetString()); - }else if (0 == strcmp(key, "layers")) { + } else if (0 == strcmp(key, "layers")) { RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { @@ -553,9 +625,9 @@ LottieParserImpl::parseAsset() asset->mLayers.push_back(layer); } } else { - #ifdef DEBUG_PARSER - vWarning<<"Asset Attribute Skipped : "< -LottieParserImpl::parseLayer() +std::shared_ptr LottieParserImpl::parseLayer() { RAPIDJSON_ASSERT(PeekType() == kObjectType); - std::shared_ptr sharedLayer = std::make_shared(); + std::shared_ptr sharedLayer = + std::make_shared(); LOTLayerData *layer = sharedLayer.get(); curLayerRef = layer; bool hasLayerRef = false; EnterObject(); - while (const char* key = NextObjectKey()) { - if (0 == strcmp(key, "ty")) { /* Type of layer*/ + while (const char *key = NextObjectKey()) { + if (0 == strcmp(key, "ty")) { /* Type of layer*/ layer->mLayerType = getLayerType(); - } else if (0 == strcmp(key, "ind")) { /*Layer index in AE. Used for parenting and expressions.*/ + } else if (0 == strcmp(key, "ind")) { /*Layer index in AE. Used for + parenting and expressions.*/ RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mId = GetInt(); - } else if (0 == strcmp(key, "parent")) { /*Layer Parent. Uses "ind" of parent.*/ + } else if (0 == + strcmp(key, + "parent")) { /*Layer Parent. Uses "ind" of parent.*/ RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mParentId = GetInt(); } else if (0 == strcmp(key, "refId")) { /*preComp Layer reference id*/ @@ -671,18 +747,18 @@ LottieParserImpl::parseLayer() layer->mPreCompRefId = std::string(GetString()); mLayersToUpdate.push_back(sharedLayer); hasLayerRef = true; - }else if (0 == strcmp(key, "sr")) { // "Layer Time Stretching" + } else if (0 == strcmp(key, "sr")) { // "Layer Time Stretching" RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mTimeStreatch = GetDouble(); - } else if (0 == strcmp(key, "tm")) { // time remapping + } else if (0 == strcmp(key, "tm")) { // time remapping parseProperty(layer->mTimeRemap); - }else if (0 == strcmp(key, "ip")) { + } else if (0 == strcmp(key, "ip")) { RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mInFrame = std::round(GetDouble()); } else if (0 == strcmp(key, "op")) { RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mOutFrame = std::round(GetDouble()); - } else if (0 == strcmp(key, "st")) { + } else if (0 == strcmp(key, "st")) { RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mStartFrame = GetDouble(); } else if (0 == strcmp(key, "bounds")) { @@ -709,10 +785,10 @@ LottieParserImpl::parseLayer() layer->mHasMask = GetBool(); } else if (0 == strcmp(key, "masksProperties")) { parseMaskProperty(layer); - }else { - #ifdef DEBUG_PARSER - vWarning<<"Layer Attribute Skipped : "<isStatic(); } - layer->setStatic(staticFlag && - layer->mTransform->isStatic() && + layer->setStatic(staticFlag && layer->mTransform->isStatic() && !hasLayerRef); return sharedLayer; @@ -742,15 +817,14 @@ void LottieParserImpl::parseMaskProperty(LOTLayerData *layer) } } -std::shared_ptr -LottieParserImpl::parseMaskObject() +std::shared_ptr LottieParserImpl::parseMaskObject() { std::shared_ptr sharedMask = std::make_shared(); - LOTMaskData *obj = sharedMask.get(); + LOTMaskData * obj = sharedMask.get(); RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "inv")) { obj->mInv = GetBool(); } else if (0 == strcmp(key, "mode")) { @@ -784,8 +858,6 @@ LottieParserImpl::parseMaskObject() return sharedMask; } - - void LottieParserImpl::parseShapesAttr(LOTLayerData *layer) { RAPIDJSON_ASSERT(PeekType() == kArrayType); @@ -795,8 +867,7 @@ void LottieParserImpl::parseShapesAttr(LOTLayerData *layer) } } -std::shared_ptr -LottieParserImpl::parseObjectTypeAttr() +std::shared_ptr LottieParserImpl::parseObjectTypeAttr() { RAPIDJSON_ASSERT(PeekType() == kStringType); const char *type = GetString(); @@ -826,23 +897,21 @@ LottieParserImpl::parseObjectTypeAttr() return parseReapeaterObject(); } else { #ifdef DEBUG_PARSER - vDebug<<"The Object Type not yet handled = "<< type; + vDebug << "The Object Type not yet handled = " << type; #endif return nullptr; } } -void -LottieParserImpl::parseObject(LOTGroupData *parent) +void LottieParserImpl::parseObject(LOTGroupData *parent) { RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "ty")) { auto child = parseObjectTypeAttr(); if (child) { - if (child) - parent->mChildren.push_back(child); + if (child) parent->mChildren.push_back(child); } } else { Skip(key); @@ -850,13 +919,13 @@ LottieParserImpl::parseObject(LOTGroupData *parent) } } -std::shared_ptr -LottieParserImpl::parseGroupObject() +std::shared_ptr LottieParserImpl::parseGroupObject() { - std::shared_ptr sharedGroup = std::make_shared(); + std::shared_ptr sharedGroup = + std::make_shared(); LOTShapeGroupData *group = sharedGroup.get(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "it")) { RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); @@ -864,7 +933,8 @@ LottieParserImpl::parseGroupObject() RAPIDJSON_ASSERT(PeekType() == kObjectType); parseObject(group); } - group->mTransform = std::dynamic_pointer_cast(group->mChildren.back()); + group->mTransform = std::dynamic_pointer_cast( + group->mChildren.back()); group->mChildren.pop_back(); } else { Skip(key); @@ -875,8 +945,7 @@ LottieParserImpl::parseGroupObject() staticFlag &= child.get()->isStatic(); } - group->setStatic(staticFlag && - group->mTransform->isStatic()); + group->setStatic(staticFlag && group->mTransform->isStatic()); return sharedGroup; } @@ -884,13 +953,12 @@ LottieParserImpl::parseGroupObject() /* * https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/rect.json */ -std::shared_ptr -LottieParserImpl::parseRectObject() +std::shared_ptr LottieParserImpl::parseRectObject() { std::shared_ptr sharedRect = std::make_shared(); - LOTRectData *obj = sharedRect.get(); + LOTRectData * obj = sharedRect.get(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "p")) { parseProperty(obj->mPos); } else if (0 == strcmp(key, "s")) { @@ -903,8 +971,7 @@ LottieParserImpl::parseRectObject() Skip(key); } } - obj->setStatic(obj->mPos.isStatic() && - obj->mSize.isStatic() && + obj->setStatic(obj->mPos.isStatic() && obj->mSize.isStatic() && obj->mRound.isStatic()); return sharedRect; } @@ -912,13 +979,13 @@ LottieParserImpl::parseRectObject() /* * https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/ellipse.json */ -std::shared_ptr -LottieParserImpl::parseEllipseObject() +std::shared_ptr LottieParserImpl::parseEllipseObject() { - std::shared_ptr sharedEllipse = std::make_shared(); + std::shared_ptr sharedEllipse = + std::make_shared(); LOTEllipseData *obj = sharedEllipse.get(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "p")) { parseProperty(obj->mPos); } else if (0 == strcmp(key, "s")) { @@ -929,28 +996,27 @@ LottieParserImpl::parseEllipseObject() Skip(key); } } - obj->setStatic(obj->mPos.isStatic() && - obj->mSize.isStatic()); + obj->setStatic(obj->mPos.isStatic() && obj->mSize.isStatic()); return sharedEllipse; } /* * https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/shape.json */ -std::shared_ptr -LottieParserImpl::parseShapeObject() +std::shared_ptr LottieParserImpl::parseShapeObject() { - std::shared_ptr sharedShape = std::make_shared(); + std::shared_ptr sharedShape = + std::make_shared(); LOTShapeData *obj = sharedShape.get(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "ks")) { parseShapeProperty(obj->mShape); } else if (0 == strcmp(key, "d")) { obj->mDirection = GetInt(); } else { #ifdef DEBUG_PARSER - vDebug<<"Shape property ignored :"< -LottieParserImpl::parsePolystarObject() +std::shared_ptr LottieParserImpl::parsePolystarObject() { - std::shared_ptr sharedPolystar = std::make_shared(); + std::shared_ptr sharedPolystar = + std::make_shared(); LOTPolystarData *obj = sharedPolystar.get(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "p")) { parseProperty(obj->mPos); } else if (0 == strcmp(key, "pt")) { @@ -986,32 +1052,27 @@ LottieParserImpl::parsePolystarObject() parseProperty(obj->mRotation); } else if (0 == strcmp(key, "sy")) { int starType = GetInt(); - if (starType == 1) - obj->mType = LOTPolystarData::PolyType::Star; - if (starType == 2) - obj->mType = LOTPolystarData::PolyType::Polygon; + if (starType == 1) obj->mType = LOTPolystarData::PolyType::Star; + if (starType == 2) obj->mType = LOTPolystarData::PolyType::Polygon; } else if (0 == strcmp(key, "d")) { obj->mDirection = GetInt(); } else { #ifdef DEBUG_PARSER - vDebug<<"Polystar property ignored :"<setStatic(obj->mPos.isStatic() && - obj->mPointCount.isStatic() && - obj->mInnerRadius.isStatic() && - obj->mInnerRoundness.isStatic() && - obj->mOuterRadius.isStatic() && - obj->mOuterRoundness.isStatic() && - obj->mRotation.isStatic()); + obj->setStatic( + obj->mPos.isStatic() && obj->mPointCount.isStatic() && + obj->mInnerRadius.isStatic() && obj->mInnerRoundness.isStatic() && + obj->mOuterRadius.isStatic() && obj->mOuterRoundness.isStatic() && + obj->mRotation.isStatic()); return sharedPolystar; } -LOTTrimData::TrimType -LottieParserImpl::getTrimType() +LOTTrimData::TrimType LottieParserImpl::getTrimType() { RAPIDJSON_ASSERT(PeekType() == kNumberType); switch (GetInt()) { @@ -1030,42 +1091,40 @@ LottieParserImpl::getTrimType() /* * https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/trim.json */ -std::shared_ptr -LottieParserImpl::parseTrimObject() +std::shared_ptr LottieParserImpl::parseTrimObject() { std::shared_ptr sharedTrim = std::make_shared(); - LOTTrimData *obj = sharedTrim.get(); + LOTTrimData * obj = sharedTrim.get(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "s")) { parseProperty(obj->mStart); } else if (0 == strcmp(key, "e")) { parseProperty(obj->mEnd); } else if (0 == strcmp(key, "o")) { parseProperty(obj->mOffset); - } else if (0 == strcmp(key, "m")) { + } else if (0 == strcmp(key, "m")) { obj->mTrimType = getTrimType(); } else { #ifdef DEBUG_PARSER - vDebug<<"Trim property ignored :"<setStatic(obj->mStart.isStatic() && - obj->mEnd.isStatic() && + obj->setStatic(obj->mStart.isStatic() && obj->mEnd.isStatic() && obj->mOffset.isStatic()); curLayerRef->mHasPathOperator = true; return sharedTrim; } -std::shared_ptr -LottieParserImpl::parseReapeaterObject() +std::shared_ptr LottieParserImpl::parseReapeaterObject() { - std::shared_ptr sharedRepeater = std::make_shared(); + std::shared_ptr sharedRepeater = + std::make_shared(); LOTRepeaterData *obj = sharedRepeater.get(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "c")) { parseProperty(obj->mCopies); } else if (0 == strcmp(key, "o")) { @@ -1074,29 +1133,27 @@ LottieParserImpl::parseReapeaterObject() obj->mTransform = parseTransformObject(); } else { #ifdef DEBUG_PARSER - vDebug<<"Repeater property ignored :"<setStatic(obj->mCopies.isStatic() && - obj->mOffset.isStatic() && + obj->setStatic(obj->mCopies.isStatic() && obj->mOffset.isStatic() && obj->mTransform->isStatic()); return sharedRepeater; } - /* * https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/transform.json */ -std::shared_ptr -LottieParserImpl::parseTransformObject() +std::shared_ptr LottieParserImpl::parseTransformObject() { - std::shared_ptr sharedTransform = std::make_shared(); + std::shared_ptr sharedTransform = + std::make_shared(); LOTTransformData *obj = sharedTransform.get(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "a")) { parseProperty(obj->mAnchor); } else if (0 == strcmp(key, "p")) { @@ -1107,7 +1164,7 @@ LottieParserImpl::parseTransformObject() parseProperty(obj->mScale); } else if (0 == strcmp(key, "sk")) { parseProperty(obj->mSkew); - } else if (0 == strcmp(key, "sa")) { + } else if (0 == strcmp(key, "sa")) { parseProperty(obj->mSkewAxis); } else if (0 == strcmp(key, "o")) { parseProperty(obj->mOpacity); @@ -1115,16 +1172,12 @@ LottieParserImpl::parseTransformObject() Skip(key); } } - obj->mStaticMatrix = obj->mAnchor.isStatic() && - obj->mPosition.isStatic() && - obj->mRotation.isStatic() && - obj->mScale.isStatic() && - obj->mSkew.isStatic() && - obj->mSkewAxis.isStatic(); - obj->setStatic(obj->mStaticMatrix && obj->mOpacity.isStatic() ); + obj->mStaticMatrix = obj->mAnchor.isStatic() && obj->mPosition.isStatic() && + obj->mRotation.isStatic() && obj->mScale.isStatic() && + obj->mSkew.isStatic() && obj->mSkewAxis.isStatic(); + obj->setStatic(obj->mStaticMatrix && obj->mOpacity.isStatic()); - if (obj->mStaticMatrix) - obj->cacheMatrix(); + if (obj->mStaticMatrix) obj->cacheMatrix(); return sharedTransform; } @@ -1132,13 +1185,12 @@ LottieParserImpl::parseTransformObject() /* * https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/fill.json */ -std::shared_ptr -LottieParserImpl::parseFillObject() +std::shared_ptr LottieParserImpl::parseFillObject() { std::shared_ptr sharedFill = std::make_shared(); - LOTFillData *obj = sharedFill.get(); + LOTFillData * obj = sharedFill.get(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "c")) { parseProperty(obj->mColor); } else if (0 == strcmp(key, "o")) { @@ -1149,13 +1201,12 @@ LottieParserImpl::parseFillObject() obj->mFillRule = getFillRule(); } else { #ifdef DEBUG_PARSER - vWarning<<"Fill property skipped = "<mColor); } else if (0 == strcmp(key, "o")) { @@ -1243,20 +1294,17 @@ LottieParserImpl::parseStrokeObject() parseDashProperty(obj->mDash); } else { #ifdef DEBUG_PARSER - vWarning<<"Stroke property skipped = "<mHighlightAngle); } else if (0 == strcmp(key, "g")) { EnterObject(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "k")) { parseProperty(obj->mGradient); } else if (0 == strcmp(key, "p")) { obj->mColorPoints = GetInt(); - } else { + } else { Skip(nullptr); } } } else { #ifdef DEBUG_PARSER - vWarning<<"Gradient property skipped = "<mFillRule = getFillRule(); } else { @@ -1325,7 +1370,7 @@ void LottieParserImpl::parseDashProperty(LOTDashProperty &dash) while (NextArrayValue()) { RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "v")) { parseProperty(dash.mDashArray[dash.mDashCount++]); } else { @@ -1335,7 +1380,7 @@ void LottieParserImpl::parseDashProperty(LOTDashProperty &dash) } // update the staic proprty - for (int i = 0 ; i < dash.mDashCount ; i++) { + for (int i = 0; i < dash.mDashCount; i++) { if (!dash.mDashArray[i].isStatic()) { dash.mStatic = false; break; @@ -1346,13 +1391,13 @@ void LottieParserImpl::parseDashProperty(LOTDashProperty &dash) /* * https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/gstroke.json */ -std::shared_ptr -LottieParserImpl::parseGStrokeObject() +std::shared_ptr LottieParserImpl::parseGStrokeObject() { - std::shared_ptr sharedGStroke = std::make_shared(); + std::shared_ptr sharedGStroke = + std::make_shared(); LOTGStrokeData *obj = sharedGStroke.get(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "w")) { parseProperty(obj->mWidth); } else if (0 == strcmp(key, "lc")) { @@ -1364,13 +1409,12 @@ LottieParserImpl::parseGStrokeObject() obj->mMeterLimit = GetDouble(); } else if (0 == strcmp(key, "d")) { parseDashProperty(obj->mDash); - } else { + } else { parseGradientProperty(obj, key); } } - obj->setStatic(obj->isStatic() && - obj->mWidth.isStatic() && + obj->setStatic(obj->isStatic() && obj->mWidth.isStatic() && obj->mDash.mStatic); return sharedGStroke; } @@ -1378,7 +1422,7 @@ LottieParserImpl::parseGStrokeObject() void LottieParserImpl::parseArrayValue(LottieColor &color) { float val[4]; - int i=0; + int i = 0; while (NextArrayValue()) { val[i++] = GetDouble(); } @@ -1391,7 +1435,7 @@ void LottieParserImpl::parseArrayValue(LottieColor &color) void LottieParserImpl::parseArrayValue(VPointF &pt) { float val[4]; - int i=0; + int i = 0; while (NextArrayValue()) { val[i++] = GetDouble(); } @@ -1427,7 +1471,7 @@ void LottieParserImpl::parseArrayValue(std::vector &v) void LottieParserImpl::getValue(VPointF &pt) { float val[4]; - int i=0; + int i = 0; RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { @@ -1454,7 +1498,7 @@ void LottieParserImpl::getValue(float &val) void LottieParserImpl::getValue(LottieColor &color) { float val[4]; - int i=0; + int i = 0; RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { @@ -1497,23 +1541,22 @@ void LottieParserImpl::getValue(int &val) void LottieParserImpl::getValue(LottieShapeData &obj) { - std::vector inPoint; /* "i" */ - std::vector outPoint; /* "o" */ - std::vector vertices; /* "v" */ - std::vector points; - bool closed=false; + std::vector inPoint; /* "i" */ + std::vector outPoint; /* "o" */ + std::vector vertices; /* "v" */ + std::vector points; + bool closed = false; /* * The shape object could be wrapped by a array * if its part of the keyframe object */ bool arrayWrapper = (PeekType() == kArrayType); - if (arrayWrapper) - EnterArray(); + if (arrayWrapper) EnterArray(); RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "i")) { parseArrayValue(inPoint); } else if (0 == strcmp(key, "o")) { @@ -1522,52 +1565,54 @@ void LottieParserImpl::getValue(LottieShapeData &obj) parseArrayValue(vertices); } else if (0 == strcmp(key, "c")) { closed = GetBool(); - }else { + } else { RAPIDJSON_ASSERT(0); Skip(nullptr); } } // exit properly from the array - if (arrayWrapper) - NextArrayValue(); - + if (arrayWrapper) NextArrayValue(); -/* - * Convert the AE shape format to - * list of bazier curves - * The final structure will be Move +size*Cubic + Cubic (if the path is closed one) - */ + /* + * Convert the AE shape format to + * list of bazier curves + * The final structure will be Move +size*Cubic + Cubic (if the path is + * closed one) + */ if (inPoint.size() != outPoint.size() || inPoint.size() != vertices.size()) { - vCritical<<"The Shape data are corrupted"; + vCritical << "The Shape data are corrupted"; points = std::vector(); } else { int size = vertices.size(); - points.reserve(3*size + 4); + points.reserve(3 * size + 4); points.push_back(vertices[0]); - for (int i =1; i -bool LottieParserImpl::parseKeyFrameValue(const char* key, LOTKeyFrameValue &value) +template +bool LottieParserImpl::parseKeyFrameValue(const char * key, + LOTKeyFrameValue &value) { if (0 == strcmp(key, "s")) { getValue(value.mStartValue); @@ -1607,8 +1653,9 @@ bool LottieParserImpl::parseKeyFrameValue(const char* key, LOTKeyFrameValue & return true; } -template<> -bool LottieParserImpl::parseKeyFrameValue(const char* key, LOTKeyFrameValue &value) +template <> +bool LottieParserImpl::parseKeyFrameValue(const char * key, + LOTKeyFrameValue &value) { if (0 == strcmp(key, "s")) { getValue(value.mStartValue); @@ -1629,73 +1676,74 @@ bool LottieParserImpl::parseKeyFrameValue(const char* key, LOTKeyFrameValue +template void LottieParserImpl::parseKeyFrame(LOTAnimInfo &obj) { EnterObject(); LOTKeyFrame keyframe; - VPointF inTangent; - VPointF outTangent; - const char *interpolatorKey = nullptr; - bool hold = false; - while (const char* key = NextObjectKey()) { - if (0 == strcmp(key, "i")) { - inTangent = parseInperpolatorPoint(); - } else if (0 == strcmp(key, "o")) { - outTangent = parseInperpolatorPoint(); - } else if (0 == strcmp(key, "n")) { - if (PeekType() == kStringType) { + VPointF inTangent; + VPointF outTangent; + const char * interpolatorKey = nullptr; + bool hold = false; + while (const char *key = NextObjectKey()) { + if (0 == strcmp(key, "i")) { + inTangent = parseInperpolatorPoint(); + } else if (0 == strcmp(key, "o")) { + outTangent = parseInperpolatorPoint(); + } else if (0 == strcmp(key, "n")) { + if (PeekType() == kStringType) { interpolatorKey = GetString(); - } else { + } else { RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { RAPIDJSON_ASSERT(PeekType() == kStringType); interpolatorKey = GetString(); } - } - continue; - } else if (0 == strcmp(key, "t")) { - keyframe.mStartFrame = GetDouble(); - } else if (parseKeyFrameValue(key, keyframe.mValue)) { - continue; - } else if (0 == strcmp(key, "h")) { - hold = GetInt(); - continue; - } else { + } + continue; + } else if (0 == strcmp(key, "t")) { + keyframe.mStartFrame = GetDouble(); + } else if (parseKeyFrameValue(key, keyframe.mValue)) { + continue; + } else if (0 == strcmp(key, "h")) { + hold = GetInt(); + continue; + } else { #ifdef DEBUG_PARSER - vDebug<<"key frame property skipped = "<mInterpolatorCache.find(interpolatorKey); - if (search != compRef->mInterpolatorCache.end()) { - keyframe.mInterpolator = search->second; - } else { - keyframe.mInterpolator = std::make_shared(VInterpolator(inTangent, outTangent)); - compRef->mInterpolatorCache[interpolatorKey] = keyframe.mInterpolator; - } - obj.mKeyFrames.push_back(keyframe); - } -} + Skip(key); + } + } + + if (!obj.mKeyFrames.empty()) { + // update the endFrame value of current keyframe + obj.mKeyFrames.back().mEndFrame = keyframe.mStartFrame; + } + if (hold) { + interpolatorKey = "hold_interpolator"; + inTangent = VPointF(); + outTangent = VPointF(); + keyframe.mValue.mEndValue = keyframe.mValue.mStartValue; + keyframe.mEndFrame = keyframe.mStartFrame; + } + + // Try to find the interpolator from cache + if (interpolatorKey) { + auto search = compRef->mInterpolatorCache.find(interpolatorKey); + if (search != compRef->mInterpolatorCache.end()) { + keyframe.mInterpolator = search->second; + } else { + keyframe.mInterpolator = std::make_shared( + VInterpolator(inTangent, outTangent)); + compRef->mInterpolatorCache[interpolatorKey] = + keyframe.mInterpolator; + } + obj.mKeyFrames.push_back(keyframe); + } +} /* * https://github.com/airbnb/lottie-web/blob/master/docs/json/properties/shapeKeyframed.json @@ -1704,18 +1752,18 @@ void LottieParserImpl::parseKeyFrame(LOTAnimInfo &obj) /* * https://github.com/airbnb/lottie-web/blob/master/docs/json/properties/shape.json */ -void -LottieParserImpl::parseShapeProperty(LOTAnimatable &obj) +void LottieParserImpl::parseShapeProperty(LOTAnimatable &obj) { EnterObject(); - while (const char* key = NextObjectKey()) { + while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "k")) { if (PeekType() == kArrayType) { EnterArray(); while (NextArrayValue()) { RAPIDJSON_ASSERT(PeekType() == kObjectType); if (!obj.mAnimInfo) - obj.mAnimInfo = std::make_unique>(); + obj.mAnimInfo = + std::make_unique>(); parseKeyFrame(*obj.mAnimInfo.get()); } } else { @@ -1723,7 +1771,7 @@ LottieParserImpl::parseShapeProperty(LOTAnimatable &obj) } } else { #ifdef DEBUG_PARSER - vDebug<<"shape property ignored = "< &obj) } } } - } else if (0 == strcmp(key, "ix")){ + } else if (0 == strcmp(key, "ix")) { RAPIDJSON_ASSERT(PeekType() == kNumberType); obj.mPropertyIndex = GetInt(); } else { @@ -1775,74 +1823,95 @@ void LottieParserImpl::parseProperty(LOTAnimatable &obj) } } -class LOTDataInspector : public LOTDataVisitor -{ +class LOTDataInspector : public LOTDataVisitor { public: - void visit(LOTCompositionData *obj) { - vDebug<<"[COMP_START:: static:"<isStatic()<<" v:"<mVersion<<" [{ stFm endFm fmRate } { "<mStartFrame<<" "<mEndFrame<<" }]\n"; - } - void visit(LOTLayerData *obj) { - vDebug<<"[LAYER_START:: type:"<mLayerType)<<" id:"<mId<<" Pid:"<mParentId - <<" static:"<isStatic()<<"[{ stFm endFm stTm tmStrch } { " - <mInFrame<<" "<mOutFrame<<" "<mStartFrame<<" "<mTimeStreatch <<" }]"; - } - void visit(LOTTransformData *t) { - vDebug<<"[TRANSFORM: static: "<isStatic()<<" ]"; - } - void visit(LOTShapeGroupData *o) { - vDebug<<"[GROUP_START:: static:"<isStatic()<<"]"; - } - void visit(LOTShapeData *s) { - vDebug<<"[SHAPE: static:"<isStatic()<<"]"; - } - void visit(LOTRectData *r) { - vDebug<<"[RECT: static:"<isStatic()<<"]"; - } - void visit(LOTEllipseData *e) { - vDebug<<"[ELLIPSE: static:"<isStatic()<<"]"; - } - void visit(LOTTrimData *t) { - vDebug<<"[TRIM: static: "<isStatic()<<" ]"; - } - void visit(LOTRepeaterData *r) { - vDebug<<"[REPEATER: static:"<isStatic()<<"]"; - } - void visit(LOTFillData *f) { - vDebug<<"[FILL: static:"<isStatic()<<"]"; - } - void visit(LOTGFillData *f) { - vDebug<<"[GFILL: static:"<isStatic()<<" ty:"<mGradientType<<" s:"<mStartPoint.value(0)<<" e:"<mEndPoint.value(0)<<"]"; - } - void visit(LOTGStrokeData *f) { - vDebug<<"[GSTROKE: static:"<isStatic()<<"]"; - } - void visit(LOTStrokeData *s) { - vDebug<<"[STROKE: static:"<isStatic()<<"]"; - } - void visitChildren(LOTGroupData *obj) { - for(auto child :obj->mChildren) - child.get()->accept(this); + void visit(LOTCompositionData *obj) + { + vDebug << "[COMP_START:: static:" << obj->isStatic() + << " v:" << obj->mVersion << " [{ stFm endFm fmRate } { " + << obj->mStartFrame << " " << obj->mEndFrame << " }]\n"; + } + void visit(LOTLayerData *obj) + { + vDebug << "[LAYER_START:: type:" << layerType(obj->mLayerType) + << " id:" << obj->mId << " Pid:" << obj->mParentId + << " static:" << obj->isStatic() + << "[{ stFm endFm stTm tmStrch } { " << obj->mInFrame << " " + << obj->mOutFrame << " " << obj->mStartFrame << " " + << obj->mTimeStreatch << " }]"; + } + void visit(LOTTransformData *t) + { + vDebug << "[TRANSFORM: static: " << t->isStatic() << " ]"; + } + void visit(LOTShapeGroupData *o) + { + vDebug << "[GROUP_START:: static:" << o->isStatic() << "]"; + } + void visit(LOTShapeData *s) + { + vDebug << "[SHAPE: static:" << s->isStatic() << "]"; + } + void visit(LOTRectData *r) + { + vDebug << "[RECT: static:" << r->isStatic() << "]"; + } + void visit(LOTEllipseData *e) + { + vDebug << "[ELLIPSE: static:" << e->isStatic() << "]"; + } + void visit(LOTTrimData *t) + { + vDebug << "[TRIM: static: " << t->isStatic() << " ]"; + } + void visit(LOTRepeaterData *r) + { + vDebug << "[REPEATER: static:" << r->isStatic() << "]"; + } + void visit(LOTFillData *f) + { + vDebug << "[FILL: static:" << f->isStatic() << "]"; + } + void visit(LOTGFillData *f) + { + vDebug << "[GFILL: static:" << f->isStatic() + << " ty:" << f->mGradientType << " s:" << f->mStartPoint.value(0) + << " e:" << f->mEndPoint.value(0) << "]"; + } + void visit(LOTGStrokeData *f) + { + vDebug << "[GSTROKE: static:" << f->isStatic() << "]"; + } + void visit(LOTStrokeData *s) + { + vDebug << "[STROKE: static:" << s->isStatic() << "]"; + } + void visitChildren(LOTGroupData *obj) + { + for (auto child : obj->mChildren) child.get()->accept(this); switch (obj->type()) { - case LOTData::Type::Layer: - { + case LOTData::Type::Layer: { LOTLayerData *layer = static_cast(obj); - vDebug<<"[LAYER_END:: type:"<mLayerType).c_str()<<" id:"<mId<<"\n"; + vDebug << "[LAYER_END:: type:" + << layerType(layer->mLayerType).c_str() + << " id:" << layer->mId << "\n"; break; } case LOTData::Type::ShapeGroup: - vDebug<<"[GROUP_END]"; + vDebug << "[GROUP_END]"; break; case LOTData::Type::Composition: - vDebug<<"[COMP End ]\n"; + vDebug << "[COMP End ]\n"; break; case LOTData::Type::Repeater: - vDebug<<"[REPEATER End ]"; + vDebug << "[REPEATER End ]"; break; default: break; } } - std::string layerType(LayerType type) { + std::string layerType(LayerType type) + { switch (type) { case LayerType::Precomp: return "Precomp"; @@ -1874,24 +1943,24 @@ LottieParser::~LottieParser() delete d; } -LottieParser::LottieParser(char* str): d(new LottieParserImpl(str)) +LottieParser::LottieParser(char *str) : d(new LottieParserImpl(str)) { d->parseComposition(); } std::shared_ptr LottieParser::model() { - std::shared_ptr model= std::make_shared(); - model->mRoot = d->composition(); - model->mRoot->processPathOperatorObjects(); - model->mRoot->processRepeaterObjects(); + std::shared_ptr model = std::make_shared(); + model->mRoot = d->composition(); + model->mRoot->processPathOperatorObjects(); + model->mRoot->processRepeaterObjects(); #ifdef DEBUG_PARSER - LOTDataInspector inspector; - model->mRoot->accept(&inspector); + LOTDataInspector inspector; + model->mRoot->accept(&inspector); #endif - return model; + return model; } RAPIDJSON_DIAG_POP diff --git a/src/lottie/lottieplayer.cpp b/src/lottie/lottieplayer.cpp index f2264be..4405290 100644 --- a/src/lottie/lottieplayer.cpp +++ b/src/lottie/lottieplayer.cpp @@ -1,32 +1,32 @@ #include -#include "lottiemodel.h" -#include "lottieloader.h" #include "lottieitem.h" +#include "lottieloader.h" +#include "lottiemodel.h" -#include - +#include -class LOTPlayerPrivate -{ +class LOTPlayerPrivate { public: - LOTPlayerPrivate(); - bool setFilePath(std::string path); - void setSize(const VSize &sz); - void size(int &w, int &h) const; - float playTime() const; - bool setPos(float pos); - float pos(); - const std::vector& renderList()const; - bool render(float pos, const LOTBuffer &buffer); + LOTPlayerPrivate(); + bool setFilePath(std::string path); + void setSize(const VSize &sz); + void size(int &w, int &h) const; + float playTime() const; + bool setPos(float pos); + float pos(); + const std::vector &renderList() const; + bool render(float pos, const LOTBuffer &buffer); + public: - std::string mFilePath; - std::shared_ptr mModel; - std::unique_ptr mCompItem; - VSize mSize; - std::atomic mRenderInProgress; + std::string mFilePath; + std::shared_ptr mModel; + std::unique_ptr mCompItem; + VSize mSize; + std::atomic mRenderInProgress; + private: - float mPos; + float mPos; }; void LOTPlayerPrivate::setSize(const VSize &sz) @@ -52,10 +52,10 @@ void LOTPlayerPrivate::size(int &w, int &h) const h = size.height(); } -const std::vector& LOTPlayerPrivate::renderList() const +const std::vector &LOTPlayerPrivate::renderList() const { if (!mCompItem.get()) { - //FIXME: Reference is not good... + // FIXME: Reference is not good... } return mCompItem->renderList(); @@ -63,34 +63,34 @@ const std::vector& LOTPlayerPrivate::renderList() const float LOTPlayerPrivate::playTime() const { - if (mModel->isStatic()) return 0; - return float(mModel->frameDuration()) / float(mModel->frameRate()); + if (mModel->isStatic()) return 0; + return float(mModel->frameDuration()) / float(mModel->frameRate()); } bool LOTPlayerPrivate::setPos(float pos) { - if (!mModel || !mCompItem) return false; + if (!mModel || !mCompItem) return false; - if (pos > 1.0) pos = 1.0; - if (pos < 0) pos = 0; - if (mModel->isStatic()) pos = 0; + if (pos > 1.0) pos = 1.0; + if (pos < 0) pos = 0; + if (mModel->isStatic()) pos = 0; - if (vCompare(pos, mPos)) return true; + if (vCompare(pos, mPos)) return true; - int frameNumber = mModel->startFrame() + pos * mModel->frameDuration(); - return mCompItem->update(frameNumber); + int frameNumber = mModel->startFrame() + pos * mModel->frameDuration(); + return mCompItem->update(frameNumber); } float LOTPlayerPrivate::pos() { - return mPos; + return mPos; } bool LOTPlayerPrivate::render(float pos, const LOTBuffer &buffer) { bool renderInProgress = mRenderInProgress.load(); if (renderInProgress) - vCritical<<"Already Rendering Scheduled for this Player"; + vCritical << "Already Rendering Scheduled for this Player"; mRenderInProgress.store(true); @@ -107,27 +107,23 @@ bool LOTPlayerPrivate::render(float pos, const LOTBuffer &buffer) return result; } -LOTPlayerPrivate::LOTPlayerPrivate():mRenderInProgress(false), mPos(-1) -{ - -} +LOTPlayerPrivate::LOTPlayerPrivate() : mRenderInProgress(false), mPos(-1) {} -bool -LOTPlayerPrivate::setFilePath(std::string path) +bool LOTPlayerPrivate::setFilePath(std::string path) { - if (path.empty()) { - vWarning << "File path is empty"; - return false; - } - - LottieLoader loader; - if (loader.load(path)) { - mModel = loader.model(); - mCompItem = std::make_unique(mModel.get()); - setPos(0); - return true; - } - return false; + if (path.empty()) { + vWarning << "File path is empty"; + return false; + } + + LottieLoader loader; + if (loader.load(path)) { + mModel = loader.model(); + mCompItem = std::make_unique(mModel.get()); + setPos(0); + return true; + } + return false; } /* @@ -137,30 +133,28 @@ LOTPlayerPrivate::setFilePath(std::string path) * on the number of cores available in the system and does a simple fair * scheduling by assigning the task in a round-robin fashion. Each thread * in the threadpool has its own queue. once it finishes all the task on its - * own queue it goes through rest of the queue and looks for task if it founds one - * it steals the task from it and executes. if it couldn't find one then it just waits - * for new task on its own queue. + * own queue it goes through rest of the queue and looks for task if it founds + * one it steals the task from it and executes. if it couldn't find one then it + * just waits for new task on its own queue. */ -struct RenderTask -{ - RenderTask() { - receiver = sender.get_future(); - } - std::promise sender; - std::future receiver; - LOTPlayerPrivate *playerImpl; - float pos; - LOTBuffer buffer; +struct RenderTask { + RenderTask() { receiver = sender.get_future(); } + std::promise sender; + std::future receiver; + LOTPlayerPrivate * playerImpl; + float pos; + LOTBuffer buffer; }; -#include +#include class RenderTaskScheduler { - const unsigned _count{std::thread::hardware_concurrency()}; + const unsigned _count{std::thread::hardware_concurrency()}; std::vector _threads; std::vector> _q{_count}; - std::atomic _index{0}; + std::atomic _index{0}; - void run(unsigned i) { + void run(unsigned i) + { while (true) { RenderTask *task = nullptr; @@ -176,21 +170,22 @@ class RenderTaskScheduler { } public: - RenderTaskScheduler() { + RenderTaskScheduler() + { for (unsigned n = 0; n != _count; ++n) { _threads.emplace_back([&, n] { run(n); }); } } - ~RenderTaskScheduler() { - for (auto& e : _q) - e.done(); + ~RenderTaskScheduler() + { + for (auto &e : _q) e.done(); - for (auto& e : _threads) - e.join(); + for (auto &e : _threads) e.join(); } - std::future async(RenderTask *task) { + std::future async(RenderTask *task) + { auto receiver = std::move(task->receiver); auto i = _index++; @@ -203,8 +198,9 @@ public: return receiver; } - std::future render(LOTPlayerPrivate *impl, - float pos, LOTBuffer &buffer) { + std::future render(LOTPlayerPrivate *impl, float pos, + LOTBuffer &buffer) + { RenderTask *task = new RenderTask(); task->playerImpl = impl; task->pos = pos; @@ -214,17 +210,13 @@ public: }; static RenderTaskScheduler render_scheduler; -LOTPlayer::LOTPlayer():d(new LOTPlayerPrivate()) -{ - -} +LOTPlayer::LOTPlayer() : d(new LOTPlayerPrivate()) {} LOTPlayer::~LOTPlayer() { - delete d; + delete d; } - /** * \breif Brief abput the Api. * Description about the setFilePath Api @@ -233,35 +225,35 @@ LOTPlayer::~LOTPlayer() bool LOTPlayer::setFilePath(const char *filePath) { - return d->setFilePath(filePath); + return d->setFilePath(filePath); } void LOTPlayer::setSize(int width, int height) { - d->setSize(VSize(width, height)); + d->setSize(VSize(width, height)); } void LOTPlayer::size(int &width, int &height) const { - d->size(width, height); + d->size(width, height); } float LOTPlayer::playTime() const { - return d->playTime(); + return d->playTime(); } void LOTPlayer::setPos(float pos) { - d->setPos(pos); + d->setPos(pos); } float LOTPlayer::pos() { - return d->pos(); + return d->pos(); } -const std::vector& LOTPlayer::renderList()const +const std::vector &LOTPlayer::renderList() const { return d->renderList(); } @@ -276,13 +268,6 @@ bool LOTPlayer::renderSync(float pos, LOTBuffer &buffer) return d->render(pos, buffer); } -LOTNode::~LOTNode() -{ -} - -LOTNode::LOTNode() -{ -} - - +LOTNode::~LOTNode() {} +LOTNode::LOTNode() {} diff --git a/src/vector/freetype/v_ft_math.cpp b/src/vector/freetype/v_ft_math.cpp index e1c8ad4..381ab6c 100644 --- a/src/vector/freetype/v_ft_math.cpp +++ b/src/vector/freetype/v_ft_math.cpp @@ -15,85 +15,69 @@ /* */ /***************************************************************************/ -#include #include "v_ft_math.h" +#include +#define SW_FT_MSB(x) (31 - __builtin_clz(x)) -#define SW_FT_MSB( x ) ( 31 - __builtin_clz( x ) ) - -#define SW_FT_PAD_FLOOR( x, n ) ( (x) & ~((n)-1) ) -#define SW_FT_PAD_ROUND( x, n ) SW_FT_PAD_FLOOR( (x) + ((n)/2), n ) -#define SW_FT_PAD_CEIL( x, n ) SW_FT_PAD_FLOOR( (x) + ((n)-1), n ) - +#define SW_FT_PAD_FLOOR(x, n) ((x) & ~((n)-1)) +#define SW_FT_PAD_ROUND(x, n) SW_FT_PAD_FLOOR((x) + ((n) / 2), n) +#define SW_FT_PAD_CEIL(x, n) SW_FT_PAD_FLOOR((x) + ((n)-1), n) -#define SW_FT_BEGIN_STMNT do { -#define SW_FT_END_STMNT } while ( 0 ) +#define SW_FT_BEGIN_STMNT do { +#define SW_FT_END_STMNT \ + } \ + while (0) /* transfer sign leaving a positive number */ -#define SW_FT_MOVE_SIGN( x, s ) \ -SW_FT_BEGIN_STMNT \ - if ( x < 0 ) \ - { \ - x = -x; \ - s = -s; \ - } \ -SW_FT_END_STMNT - - - - -SW_FT_Long -SW_FT_MulFix( SW_FT_Long a, - SW_FT_Long b ) +#define SW_FT_MOVE_SIGN(x, s) \ + SW_FT_BEGIN_STMNT \ + if (x < 0) { \ + x = -x; \ + s = -s; \ + } \ + SW_FT_END_STMNT + +SW_FT_Long SW_FT_MulFix(SW_FT_Long a, SW_FT_Long b) { - SW_FT_Int s = 1; - SW_FT_Long c; + SW_FT_Int s = 1; + SW_FT_Long c; + SW_FT_MOVE_SIGN(a, s); + SW_FT_MOVE_SIGN(b, s); - SW_FT_MOVE_SIGN( a, s ); - SW_FT_MOVE_SIGN( b, s ); + c = (SW_FT_Long)(((SW_FT_Int64)a * b + 0x8000L) >> 16); - c = (SW_FT_Long)( ( (SW_FT_Int64)a * b + 0x8000L ) >> 16 ); - - return ( s > 0 ) ? c : -c; + return (s > 0) ? c : -c; } -SW_FT_Long -SW_FT_MulDiv( SW_FT_Long a, - SW_FT_Long b, - SW_FT_Long c ) +SW_FT_Long SW_FT_MulDiv(SW_FT_Long a, SW_FT_Long b, SW_FT_Long c) { - SW_FT_Int s = 1; - SW_FT_Long d; - + SW_FT_Int s = 1; + SW_FT_Long d; - SW_FT_MOVE_SIGN( a, s ); - SW_FT_MOVE_SIGN( b, s ); - SW_FT_MOVE_SIGN( c, s ); + SW_FT_MOVE_SIGN(a, s); + SW_FT_MOVE_SIGN(b, s); + SW_FT_MOVE_SIGN(c, s); - d = (SW_FT_Long)( c > 0 ? ( (SW_FT_Int64)a * b + ( c >> 1 ) ) / c - : 0x7FFFFFFFL ); + d = (SW_FT_Long)(c > 0 ? ((SW_FT_Int64)a * b + (c >> 1)) / c : 0x7FFFFFFFL); - return ( s > 0 ) ? d : -d; + return (s > 0) ? d : -d; } -SW_FT_Long -SW_FT_DivFix( SW_FT_Long a, - SW_FT_Long b ) +SW_FT_Long SW_FT_DivFix(SW_FT_Long a, SW_FT_Long b) { - SW_FT_Int s = 1; - SW_FT_Long q; + SW_FT_Int s = 1; + SW_FT_Long q; + SW_FT_MOVE_SIGN(a, s); + SW_FT_MOVE_SIGN(b, s); - SW_FT_MOVE_SIGN( a, s ); - SW_FT_MOVE_SIGN( b, s ); + q = (SW_FT_Long)(b > 0 ? (((SW_FT_UInt64)a << 16) + (b >> 1)) / b + : 0x7FFFFFFFL); - q = (SW_FT_Long)( b > 0 ? ( ( (SW_FT_UInt64)a << 16 ) + ( b >> 1 ) ) / b - : 0x7FFFFFFFL ); - - return ( s < 0 ? -q : q ); + return (s < 0 ? -q : q); } - /*************************************************************************/ /* */ /* This is a fixed-point CORDIC implementation of trigonometric */ @@ -108,421 +92,334 @@ SW_FT_DivFix( SW_FT_Long a, /* */ /*************************************************************************/ - /* the Cordic shrink factor 0.858785336480436 * 2^32 */ -#define SW_FT_TRIG_SCALE 0xDBD95B16UL - - /* the highest bit in overflow-safe vector components, */ - /* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */ -#define SW_FT_TRIG_SAFE_MSB 29 - - /* this table was generated for SW_FT_PI = 180L << 16, i.e. degrees */ -#define SW_FT_TRIG_MAX_ITERS 23 - - static const SW_FT_Fixed - ft_trig_arctan_table[] = - { - 1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L, - 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L, - 57L, 29L, 14L, 7L, 4L, 2L, 1L - }; +/* the Cordic shrink factor 0.858785336480436 * 2^32 */ +#define SW_FT_TRIG_SCALE 0xDBD95B16UL - /* multiply a given value by the CORDIC shrink factor */ - static SW_FT_Fixed - ft_trig_downscale( SW_FT_Fixed val ) - { - SW_FT_Fixed s; - SW_FT_Int64 v; +/* the highest bit in overflow-safe vector components, */ +/* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */ +#define SW_FT_TRIG_SAFE_MSB 29 +/* this table was generated for SW_FT_PI = 180L << 16, i.e. degrees */ +#define SW_FT_TRIG_MAX_ITERS 23 - s = val; - val = SW_FT_ABS( val ); +static const SW_FT_Fixed ft_trig_arctan_table[] = { + 1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L, 14668L, + 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L, 57L, + 29L, 14L, 7L, 4L, 2L, 1L}; - v = ( val * (SW_FT_Int64)SW_FT_TRIG_SCALE ) + 0x100000000UL; - val = (SW_FT_Fixed)( v >> 32 ); - - return ( s >= 0 ) ? val : -val; - } +/* multiply a given value by the CORDIC shrink factor */ +static SW_FT_Fixed ft_trig_downscale(SW_FT_Fixed val) +{ + SW_FT_Fixed s; + SW_FT_Int64 v; + s = val; + val = SW_FT_ABS(val); + v = (val * (SW_FT_Int64)SW_FT_TRIG_SCALE) + 0x100000000UL; + val = (SW_FT_Fixed)(v >> 32); - /* undefined and never called for zero vector */ - static SW_FT_Int - ft_trig_prenorm( SW_FT_Vector* vec ) - { - SW_FT_Pos x, y; - SW_FT_Int shift; + return (s >= 0) ? val : -val; +} +/* undefined and never called for zero vector */ +static SW_FT_Int ft_trig_prenorm(SW_FT_Vector* vec) +{ + SW_FT_Pos x, y; + SW_FT_Int shift; x = vec->x; y = vec->y; - shift = SW_FT_MSB( SW_FT_ABS( x ) | SW_FT_ABS( y ) ); - - if ( shift <= SW_FT_TRIG_SAFE_MSB ) - { - shift = SW_FT_TRIG_SAFE_MSB - shift; - vec->x = (SW_FT_Pos)( (SW_FT_ULong)x << shift ); - vec->y = (SW_FT_Pos)( (SW_FT_ULong)y << shift ); - } - else - { - shift -= SW_FT_TRIG_SAFE_MSB; - vec->x = x >> shift; - vec->y = y >> shift; - shift = -shift; + shift = SW_FT_MSB(SW_FT_ABS(x) | SW_FT_ABS(y)); + + if (shift <= SW_FT_TRIG_SAFE_MSB) { + shift = SW_FT_TRIG_SAFE_MSB - shift; + vec->x = (SW_FT_Pos)((SW_FT_ULong)x << shift); + vec->y = (SW_FT_Pos)((SW_FT_ULong)y << shift); + } else { + shift -= SW_FT_TRIG_SAFE_MSB; + vec->x = x >> shift; + vec->y = y >> shift; + shift = -shift; } return shift; - } - - - static void - ft_trig_pseudo_rotate( SW_FT_Vector* vec, - SW_FT_Angle theta ) - { - SW_FT_Int i; - SW_FT_Fixed x, y, xtemp, b; - const SW_FT_Fixed *arctanptr; +} +static void ft_trig_pseudo_rotate(SW_FT_Vector* vec, SW_FT_Angle theta) +{ + SW_FT_Int i; + SW_FT_Fixed x, y, xtemp, b; + const SW_FT_Fixed* arctanptr; x = vec->x; y = vec->y; /* Rotate inside [-PI/4,PI/4] sector */ - while ( theta < -SW_FT_ANGLE_PI4 ) - { - xtemp = y; - y = -x; - x = xtemp; - theta += SW_FT_ANGLE_PI2; + while (theta < -SW_FT_ANGLE_PI4) { + xtemp = y; + y = -x; + x = xtemp; + theta += SW_FT_ANGLE_PI2; } - while ( theta > SW_FT_ANGLE_PI4 ) - { - xtemp = -y; - y = x; - x = xtemp; - theta -= SW_FT_ANGLE_PI2; + while (theta > SW_FT_ANGLE_PI4) { + xtemp = -y; + y = x; + x = xtemp; + theta -= SW_FT_ANGLE_PI2; } arctanptr = ft_trig_arctan_table; /* Pseudorotations, with right shifts */ - for ( i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++ ) - { - if ( theta < 0 ) - { - xtemp = x + ( ( y + b ) >> i ); - y = y - ( ( x + b ) >> i ); - x = xtemp; - theta += *arctanptr++; - } - else - { - xtemp = x - ( ( y + b ) >> i ); - y = y + ( ( x + b ) >> i ); - x = xtemp; - theta -= *arctanptr++; - } + for (i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++) { + if (theta < 0) { + xtemp = x + ((y + b) >> i); + y = y - ((x + b) >> i); + x = xtemp; + theta += *arctanptr++; + } else { + xtemp = x - ((y + b) >> i); + y = y + ((x + b) >> i); + x = xtemp; + theta -= *arctanptr++; + } } vec->x = x; vec->y = y; - } - - - static void - ft_trig_pseudo_polarize( SW_FT_Vector* vec ) - { - SW_FT_Angle theta; - SW_FT_Int i; - SW_FT_Fixed x, y, xtemp, b; - const SW_FT_Fixed *arctanptr; +} +static void ft_trig_pseudo_polarize(SW_FT_Vector* vec) +{ + SW_FT_Angle theta; + SW_FT_Int i; + SW_FT_Fixed x, y, xtemp, b; + const SW_FT_Fixed* arctanptr; x = vec->x; y = vec->y; /* Get the vector into [-PI/4,PI/4] sector */ - if ( y > x ) - { - if ( y > -x ) - { - theta = SW_FT_ANGLE_PI2; - xtemp = y; - y = -x; - x = xtemp; - } - else - { - theta = y > 0 ? SW_FT_ANGLE_PI : -SW_FT_ANGLE_PI; - x = -x; - y = -y; - } - } - else - { - if ( y < -x ) - { - theta = -SW_FT_ANGLE_PI2; - xtemp = -y; - y = x; - x = xtemp; - } - else - { - theta = 0; - } + if (y > x) { + if (y > -x) { + theta = SW_FT_ANGLE_PI2; + xtemp = y; + y = -x; + x = xtemp; + } else { + theta = y > 0 ? SW_FT_ANGLE_PI : -SW_FT_ANGLE_PI; + x = -x; + y = -y; + } + } else { + if (y < -x) { + theta = -SW_FT_ANGLE_PI2; + xtemp = -y; + y = x; + x = xtemp; + } else { + theta = 0; + } } arctanptr = ft_trig_arctan_table; /* Pseudorotations, with right shifts */ - for ( i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++ ) - { - if ( y > 0 ) - { - xtemp = x + ( ( y + b ) >> i ); - y = y - ( ( x + b ) >> i ); - x = xtemp; - theta += *arctanptr++; - } - else - { - xtemp = x - ( ( y + b ) >> i ); - y = y + ( ( x + b ) >> i ); - x = xtemp; - theta -= *arctanptr++; - } + for (i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++) { + if (y > 0) { + xtemp = x + ((y + b) >> i); + y = y - ((x + b) >> i); + x = xtemp; + theta += *arctanptr++; + } else { + xtemp = x - ((y + b) >> i); + y = y + ((x + b) >> i); + x = xtemp; + theta -= *arctanptr++; + } } /* round theta */ - if ( theta >= 0 ) - theta = SW_FT_PAD_ROUND( theta, 32 ); + if (theta >= 0) + theta = SW_FT_PAD_ROUND(theta, 32); else - theta = -SW_FT_PAD_ROUND( -theta, 32 ); + theta = -SW_FT_PAD_ROUND(-theta, 32); vec->x = x; vec->y = theta; - } - - - /* documentation is in fttrigon.h */ +} - SW_FT_Fixed - SW_FT_Cos( SW_FT_Angle angle ) - { - SW_FT_Vector v; +/* documentation is in fttrigon.h */ +SW_FT_Fixed SW_FT_Cos(SW_FT_Angle angle) +{ + SW_FT_Vector v; v.x = SW_FT_TRIG_SCALE >> 8; v.y = 0; - ft_trig_pseudo_rotate( &v, angle ); - - return ( v.x + 0x80L ) >> 8; - } - + ft_trig_pseudo_rotate(&v, angle); - /* documentation is in fttrigon.h */ - - SW_FT_Fixed - SW_FT_Sin( SW_FT_Angle angle ) - { - return SW_FT_Cos( SW_FT_ANGLE_PI2 - angle ); - } + return (v.x + 0x80L) >> 8; +} +/* documentation is in fttrigon.h */ - /* documentation is in fttrigon.h */ +SW_FT_Fixed SW_FT_Sin(SW_FT_Angle angle) +{ + return SW_FT_Cos(SW_FT_ANGLE_PI2 - angle); +} - SW_FT_Fixed - SW_FT_Tan( SW_FT_Angle angle ) - { - SW_FT_Vector v; +/* documentation is in fttrigon.h */ +SW_FT_Fixed SW_FT_Tan(SW_FT_Angle angle) +{ + SW_FT_Vector v; v.x = SW_FT_TRIG_SCALE >> 8; v.y = 0; - ft_trig_pseudo_rotate( &v, angle ); - - return SW_FT_DivFix( v.y, v.x ); - } - + ft_trig_pseudo_rotate(&v, angle); - /* documentation is in fttrigon.h */ + return SW_FT_DivFix(v.y, v.x); +} - SW_FT_Angle - SW_FT_Atan2( SW_FT_Fixed dx, - SW_FT_Fixed dy ) - { - SW_FT_Vector v; +/* documentation is in fttrigon.h */ +SW_FT_Angle SW_FT_Atan2(SW_FT_Fixed dx, SW_FT_Fixed dy) +{ + SW_FT_Vector v; - if ( dx == 0 && dy == 0 ) - return 0; + if (dx == 0 && dy == 0) return 0; v.x = dx; v.y = dy; - ft_trig_prenorm( &v ); - ft_trig_pseudo_polarize( &v ); + ft_trig_prenorm(&v); + ft_trig_pseudo_polarize(&v); return v.y; - } - +} - /* documentation is in fttrigon.h */ +/* documentation is in fttrigon.h */ - void - SW_FT_Vector_Unit( SW_FT_Vector* vec, - SW_FT_Angle angle ) - { +void SW_FT_Vector_Unit(SW_FT_Vector* vec, SW_FT_Angle angle) +{ vec->x = SW_FT_TRIG_SCALE >> 8; vec->y = 0; - ft_trig_pseudo_rotate( vec, angle ); - vec->x = ( vec->x + 0x80L ) >> 8; - vec->y = ( vec->y + 0x80L ) >> 8; - } - - - /* these macros return 0 for positive numbers, - and -1 for negative ones */ -#define SW_FT_SIGN_LONG( x ) ( (x) >> ( SW_FT_SIZEOF_LONG * 8 - 1 ) ) -#define SW_FT_SIGN_INT( x ) ( (x) >> ( SW_FT_SIZEOF_INT * 8 - 1 ) ) -#define SW_FT_SIGN_INT32( x ) ( (x) >> 31 ) -#define SW_FT_SIGN_INT16( x ) ( (x) >> 15 ) - - - /* documentation is in fttrigon.h */ - - void - SW_FT_Vector_Rotate( SW_FT_Vector* vec, - SW_FT_Angle angle ) - { - SW_FT_Int shift; - SW_FT_Vector v; - - - v.x = vec->x; - v.y = vec->y; - - if ( angle && ( v.x != 0 || v.y != 0 ) ) - { - shift = ft_trig_prenorm( &v ); - ft_trig_pseudo_rotate( &v, angle ); - v.x = ft_trig_downscale( v.x ); - v.y = ft_trig_downscale( v.y ); - - if ( shift > 0 ) - { - SW_FT_Int32 half = (SW_FT_Int32)1L << ( shift - 1 ); - - - vec->x = ( v.x + half + SW_FT_SIGN_LONG( v.x ) ) >> shift; - vec->y = ( v.y + half + SW_FT_SIGN_LONG( v.y ) ) >> shift; - } - else - { - shift = -shift; - vec->x = (SW_FT_Pos)( (SW_FT_ULong)v.x << shift ); - vec->y = (SW_FT_Pos)( (SW_FT_ULong)v.y << shift ); - } - } - } + ft_trig_pseudo_rotate(vec, angle); + vec->x = (vec->x + 0x80L) >> 8; + vec->y = (vec->y + 0x80L) >> 8; +} +/* these macros return 0 for positive numbers, + and -1 for negative ones */ +#define SW_FT_SIGN_LONG(x) ((x) >> (SW_FT_SIZEOF_LONG * 8 - 1)) +#define SW_FT_SIGN_INT(x) ((x) >> (SW_FT_SIZEOF_INT * 8 - 1)) +#define SW_FT_SIGN_INT32(x) ((x) >> 31) +#define SW_FT_SIGN_INT16(x) ((x) >> 15) - /* documentation is in fttrigon.h */ +/* documentation is in fttrigon.h */ - SW_FT_Fixed - SW_FT_Vector_Length( SW_FT_Vector* vec ) - { - SW_FT_Int shift; - SW_FT_Vector v; +void SW_FT_Vector_Rotate(SW_FT_Vector* vec, SW_FT_Angle angle) +{ + SW_FT_Int shift; + SW_FT_Vector v; + + v.x = vec->x; + v.y = vec->y; + + if (angle && (v.x != 0 || v.y != 0)) { + shift = ft_trig_prenorm(&v); + ft_trig_pseudo_rotate(&v, angle); + v.x = ft_trig_downscale(v.x); + v.y = ft_trig_downscale(v.y); + + if (shift > 0) { + SW_FT_Int32 half = (SW_FT_Int32)1L << (shift - 1); + + vec->x = (v.x + half + SW_FT_SIGN_LONG(v.x)) >> shift; + vec->y = (v.y + half + SW_FT_SIGN_LONG(v.y)) >> shift; + } else { + shift = -shift; + vec->x = (SW_FT_Pos)((SW_FT_ULong)v.x << shift); + vec->y = (SW_FT_Pos)((SW_FT_ULong)v.y << shift); + } + } +} + +/* documentation is in fttrigon.h */ +SW_FT_Fixed SW_FT_Vector_Length(SW_FT_Vector* vec) +{ + SW_FT_Int shift; + SW_FT_Vector v; v = *vec; /* handle trivial cases */ - if ( v.x == 0 ) - { - return SW_FT_ABS( v.y ); - } - else if ( v.y == 0 ) - { - return SW_FT_ABS( v.x ); + if (v.x == 0) { + return SW_FT_ABS(v.y); + } else if (v.y == 0) { + return SW_FT_ABS(v.x); } /* general case */ - shift = ft_trig_prenorm( &v ); - ft_trig_pseudo_polarize( &v ); - - v.x = ft_trig_downscale( v.x ); + shift = ft_trig_prenorm(&v); + ft_trig_pseudo_polarize(&v); - if ( shift > 0 ) - return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift; + v.x = ft_trig_downscale(v.x); - return (SW_FT_Fixed)( (SW_FT_UInt32)v.x << -shift ); - } + if (shift > 0) return (v.x + (1 << (shift - 1))) >> shift; + return (SW_FT_Fixed)((SW_FT_UInt32)v.x << -shift); +} - /* documentation is in fttrigon.h */ - - void - SW_FT_Vector_Polarize( SW_FT_Vector* vec, - SW_FT_Fixed *length, - SW_FT_Angle *angle ) - { - SW_FT_Int shift; - SW_FT_Vector v; +/* documentation is in fttrigon.h */ +void SW_FT_Vector_Polarize(SW_FT_Vector* vec, SW_FT_Fixed* length, + SW_FT_Angle* angle) +{ + SW_FT_Int shift; + SW_FT_Vector v; v = *vec; - if ( v.x == 0 && v.y == 0 ) - return; - - shift = ft_trig_prenorm( &v ); - ft_trig_pseudo_polarize( &v ); + if (v.x == 0 && v.y == 0) return; - v.x = ft_trig_downscale( v.x ); + shift = ft_trig_prenorm(&v); + ft_trig_pseudo_polarize(&v); - *length = ( shift >= 0 ) ? ( v.x >> shift ) - : (SW_FT_Fixed)( (SW_FT_UInt32)v.x << -shift ); - *angle = v.y; - } + v.x = ft_trig_downscale(v.x); + *length = (shift >= 0) ? (v.x >> shift) + : (SW_FT_Fixed)((SW_FT_UInt32)v.x << -shift); + *angle = v.y; +} - /* documentation is in fttrigon.h */ +/* documentation is in fttrigon.h */ - void - SW_FT_Vector_From_Polar( SW_FT_Vector* vec, - SW_FT_Fixed length, - SW_FT_Angle angle ) - { +void SW_FT_Vector_From_Polar(SW_FT_Vector* vec, SW_FT_Fixed length, + SW_FT_Angle angle) +{ vec->x = length; vec->y = 0; - SW_FT_Vector_Rotate( vec, angle ); - } - - - /* documentation is in fttrigon.h */ + SW_FT_Vector_Rotate(vec, angle); +} - SW_FT_Angle - SW_FT_Angle_Diff( SW_FT_Angle angle1, - SW_FT_Angle angle2 ) - { - SW_FT_Angle delta = angle2 - angle1; +/* documentation is in fttrigon.h */ +SW_FT_Angle SW_FT_Angle_Diff(SW_FT_Angle angle1, SW_FT_Angle angle2) +{ + SW_FT_Angle delta = angle2 - angle1; delta %= SW_FT_ANGLE_2PI; - if ( delta < 0 ) - delta += SW_FT_ANGLE_2PI; + if (delta < 0) delta += SW_FT_ANGLE_2PI; - if ( delta > SW_FT_ANGLE_PI ) - delta -= SW_FT_ANGLE_2PI; + if (delta > SW_FT_ANGLE_PI) delta -= SW_FT_ANGLE_2PI; return delta; - } - +} /* END */ - diff --git a/src/vector/freetype/v_ft_raster.cpp b/src/vector/freetype/v_ft_raster.cpp index 88f9d26..7e668f3 100644 --- a/src/vector/freetype/v_ft_raster.cpp +++ b/src/vector/freetype/v_ft_raster.cpp @@ -15,176 +15,144 @@ /* */ /***************************************************************************/ - /*************************************************************************/ - /* */ - /* This is a new anti-aliasing scan-converter for FreeType 2. The */ - /* algorithm used here is _very_ different from the one in the standard */ - /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */ - /* coverage of the outline on each pixel cell. */ - /* */ - /* It is based on ideas that I initially found in Raph Levien's */ - /* excellent LibArt graphics library (see http://www.levien.com/libart */ - /* for more information, though the web pages do not tell anything */ - /* about the renderer; you'll have to dive into the source code to */ - /* understand how it works). */ - /* */ - /* Note, however, that this is a _very_ different implementation */ - /* compared to Raph's. Coverage information is stored in a very */ - /* different way, and I don't use sorted vector paths. Also, it doesn't */ - /* use floating point values. */ - /* */ - /* This renderer has the following advantages: */ - /* */ - /* - It doesn't need an intermediate bitmap. Instead, one can supply a */ - /* callback function that will be called by the renderer to draw gray */ - /* spans on any target surface. You can thus do direct composition on */ - /* any kind of bitmap, provided that you give the renderer the right */ - /* callback. */ - /* */ - /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */ - /* each pixel cell. */ - /* */ - /* - It performs a single pass on the outline (the `standard' FT2 */ - /* renderer makes two passes). */ - /* */ - /* - It can easily be modified to render to _any_ number of gray levels */ - /* cheaply. */ - /* */ - /* - For small (< 20) pixel sizes, it is faster than the standard */ - /* renderer. */ - /* */ - /*************************************************************************/ - +/*************************************************************************/ +/* */ +/* This is a new anti-aliasing scan-converter for FreeType 2. The */ +/* algorithm used here is _very_ different from the one in the standard */ +/* `ftraster' module. Actually, `ftgrays' computes the _exact_ */ +/* coverage of the outline on each pixel cell. */ +/* */ +/* It is based on ideas that I initially found in Raph Levien's */ +/* excellent LibArt graphics library (see http://www.levien.com/libart */ +/* for more information, though the web pages do not tell anything */ +/* about the renderer; you'll have to dive into the source code to */ +/* understand how it works). */ +/* */ +/* Note, however, that this is a _very_ different implementation */ +/* compared to Raph's. Coverage information is stored in a very */ +/* different way, and I don't use sorted vector paths. Also, it doesn't */ +/* use floating point values. */ +/* */ +/* This renderer has the following advantages: */ +/* */ +/* - It doesn't need an intermediate bitmap. Instead, one can supply a */ +/* callback function that will be called by the renderer to draw gray */ +/* spans on any target surface. You can thus do direct composition on */ +/* any kind of bitmap, provided that you give the renderer the right */ +/* callback. */ +/* */ +/* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */ +/* each pixel cell. */ +/* */ +/* - It performs a single pass on the outline (the `standard' FT2 */ +/* renderer makes two passes). */ +/* */ +/* - It can easily be modified to render to _any_ number of gray levels */ +/* cheaply. */ +/* */ +/* - For small (< 20) pixel sizes, it is faster than the standard */ +/* renderer. */ +/* */ +/*************************************************************************/ #include "v_ft_raster.h" #include "v_ft_math.h" - /* Auxiliary macros for token concatenation. */ -#define SW_FT_ERR_XCAT( x, y ) x ## y -#define SW_FT_ERR_CAT( x, y ) SW_FT_ERR_XCAT( x, y ) - -#define SW_FT_BEGIN_STMNT do { -#define SW_FT_END_STMNT } while ( 0 ) +/* Auxiliary macros for token concatenation. */ +#define SW_FT_ERR_XCAT(x, y) x##y +#define SW_FT_ERR_CAT(x, y) SW_FT_ERR_XCAT(x, y) +#define SW_FT_BEGIN_STMNT do { +#define SW_FT_END_STMNT \ + } \ + while (0) +#include +#include #include #include -#include -#include -#define SW_FT_UINT_MAX UINT_MAX -#define SW_FT_INT_MAX INT_MAX -#define SW_FT_ULONG_MAX ULONG_MAX -#define SW_FT_CHAR_BIT CHAR_BIT +#define SW_FT_UINT_MAX UINT_MAX +#define SW_FT_INT_MAX INT_MAX +#define SW_FT_ULONG_MAX ULONG_MAX +#define SW_FT_CHAR_BIT CHAR_BIT -#define ft_memset memset +#define ft_memset memset -#define ft_setjmp setjmp -#define ft_longjmp longjmp -#define ft_jmp_buf jmp_buf +#define ft_setjmp setjmp +#define ft_longjmp longjmp +#define ft_jmp_buf jmp_buf -typedef ptrdiff_t SW_FT_PtrDist; +typedef ptrdiff_t SW_FT_PtrDist; - -#define ErrRaster_Invalid_Mode -2 -#define ErrRaster_Invalid_Outline -1 -#define ErrRaster_Invalid_Argument -3 -#define ErrRaster_Memory_Overflow -4 +#define ErrRaster_Invalid_Mode -2 +#define ErrRaster_Invalid_Outline -1 +#define ErrRaster_Invalid_Argument -3 +#define ErrRaster_Memory_Overflow -4 #define SW_FT_BEGIN_HEADER #define SW_FT_END_HEADER +/* This macro is used to indicate that a function parameter is unused. */ +/* Its purpose is simply to reduce compiler warnings. Note also that */ +/* simply defining it as `(void)x' doesn't avoid warnings with certain */ +/* ANSI compilers (e.g. LCC). */ +#define SW_FT_UNUSED(x) (x) = (x) - /* This macro is used to indicate that a function parameter is unused. */ - /* Its purpose is simply to reduce compiler warnings. Note also that */ - /* simply defining it as `(void)x' doesn't avoid warnings with certain */ - /* ANSI compilers (e.g. LCC). */ -#define SW_FT_UNUSED( x ) (x) = (x) - - -#define SW_FT_THROW( e ) SW_FT_ERR_CAT( ErrRaster_, e ) +#define SW_FT_THROW(e) SW_FT_ERR_CAT(ErrRaster_, e) - /* The size in bytes of the render pool used by the scan-line converter */ - /* to do all of its work. */ -#define SW_FT_RENDER_POOL_SIZE 16384L +/* The size in bytes of the render pool used by the scan-line converter */ +/* to do all of its work. */ +#define SW_FT_RENDER_POOL_SIZE 16384L -typedef int -(*SW_FT_Outline_MoveToFunc)( const SW_FT_Vector* to, - void* user ); +typedef int (*SW_FT_Outline_MoveToFunc)(const SW_FT_Vector* to, void* user); -#define SW_FT_Outline_MoveTo_Func SW_FT_Outline_MoveToFunc +#define SW_FT_Outline_MoveTo_Func SW_FT_Outline_MoveToFunc -typedef int -(*SW_FT_Outline_LineToFunc)( const SW_FT_Vector* to, - void* user ); +typedef int (*SW_FT_Outline_LineToFunc)(const SW_FT_Vector* to, void* user); -#define SW_FT_Outline_LineTo_Func SW_FT_Outline_LineToFunc +#define SW_FT_Outline_LineTo_Func SW_FT_Outline_LineToFunc +typedef int (*SW_FT_Outline_ConicToFunc)(const SW_FT_Vector* control, + const SW_FT_Vector* to, void* user); -typedef int -(*SW_FT_Outline_ConicToFunc)( const SW_FT_Vector* control, - const SW_FT_Vector* to, - void* user ); +#define SW_FT_Outline_ConicTo_Func SW_FT_Outline_ConicToFunc -#define SW_FT_Outline_ConicTo_Func SW_FT_Outline_ConicToFunc +typedef int (*SW_FT_Outline_CubicToFunc)(const SW_FT_Vector* control1, + const SW_FT_Vector* control2, + const SW_FT_Vector* to, void* user); -typedef int -(*SW_FT_Outline_CubicToFunc)( const SW_FT_Vector* control1, - const SW_FT_Vector* control2, - const SW_FT_Vector* to, - void* user ); +#define SW_FT_Outline_CubicTo_Func SW_FT_Outline_CubicToFunc -#define SW_FT_Outline_CubicTo_Func SW_FT_Outline_CubicToFunc +typedef struct SW_FT_Outline_Funcs_ { + SW_FT_Outline_MoveToFunc move_to; + SW_FT_Outline_LineToFunc line_to; + SW_FT_Outline_ConicToFunc conic_to; + SW_FT_Outline_CubicToFunc cubic_to; -typedef struct SW_FT_Outline_Funcs_ -{ - SW_FT_Outline_MoveToFunc move_to; - SW_FT_Outline_LineToFunc line_to; - SW_FT_Outline_ConicToFunc conic_to; - SW_FT_Outline_CubicToFunc cubic_to; - - int shift; - SW_FT_Pos delta; + int shift; + SW_FT_Pos delta; } SW_FT_Outline_Funcs; +#define SW_FT_DEFINE_OUTLINE_FUNCS(class_, move_to_, line_to_, conic_to_, \ + cubic_to_, shift_, delta_) \ + static const SW_FT_Outline_Funcs class_ = {move_to_, line_to_, conic_to_, \ + cubic_to_, shift_, delta_}; - -#define SW_FT_DEFINE_OUTLINE_FUNCS( class_, \ - move_to_, line_to_, \ - conic_to_, cubic_to_, \ - shift_, delta_ ) \ - static const SW_FT_Outline_Funcs class_ = \ - { \ - move_to_, \ - line_to_, \ - conic_to_, \ - cubic_to_, \ - shift_, \ - delta_ \ - }; - -#define SW_FT_DEFINE_RASTER_FUNCS( class_, \ - raster_new_, raster_reset_, \ - raster_render_, \ - raster_done_ ) \ - const SW_FT_Raster_Funcs class_ = \ - { \ - raster_new_, \ - raster_reset_, \ - raster_render_, \ - raster_done_ \ - }; - +#define SW_FT_DEFINE_RASTER_FUNCS(class_, raster_new_, raster_reset_, \ + raster_render_, raster_done_) \ + const SW_FT_Raster_Funcs class_ = {raster_new_, raster_reset_, \ + raster_render_, raster_done_}; #ifndef SW_FT_MEM_SET -#define SW_FT_MEM_SET( d, s, c ) ft_memset( d, s, c ) +#define SW_FT_MEM_SET(d, s, c) ft_memset(d, s, c) #endif #ifndef SW_FT_MEM_ZERO -#define SW_FT_MEM_ZERO( dest, count ) SW_FT_MEM_SET( dest, 0, count ) +#define SW_FT_MEM_ZERO(dest, count) SW_FT_MEM_SET(dest, 0, count) #endif - /* as usual, for the speed hungry :-) */ +/* as usual, for the speed hungry :-) */ #undef RAS_ARG #undef RAS_ARG_ @@ -193,246 +161,222 @@ typedef struct SW_FT_Outline_Funcs_ #ifndef SW_FT_STATIC_RASTER -#define RAS_ARG gray_PWorker worker -#define RAS_ARG_ gray_PWorker worker, +#define RAS_ARG gray_PWorker worker +#define RAS_ARG_ gray_PWorker worker, -#define RAS_VAR worker -#define RAS_VAR_ worker, +#define RAS_VAR worker +#define RAS_VAR_ worker, #else /* SW_FT_STATIC_RASTER */ -#define RAS_ARG /* empty */ -#define RAS_ARG_ /* empty */ -#define RAS_VAR /* empty */ -#define RAS_VAR_ /* empty */ +#define RAS_ARG /* empty */ +#define RAS_ARG_ /* empty */ +#define RAS_VAR /* empty */ +#define RAS_VAR_ /* empty */ #endif /* SW_FT_STATIC_RASTER */ - - /* must be at least 6 bits! */ -#define PIXEL_BITS 8 +/* must be at least 6 bits! */ +#define PIXEL_BITS 8 #undef FLOOR #undef CEILING #undef TRUNC #undef SCALED -#define ONE_PIXEL ( 1L << PIXEL_BITS ) -#define PIXEL_MASK ( -1L << PIXEL_BITS ) -#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) ) -#define SUBPIXELS( x ) ( (TPos)(x) << PIXEL_BITS ) -#define FLOOR( x ) ( (x) & -ONE_PIXEL ) -#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL ) -#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL ) +#define ONE_PIXEL (1L << PIXEL_BITS) +#define PIXEL_MASK (-1L << PIXEL_BITS) +#define TRUNC(x) ((TCoord)((x) >> PIXEL_BITS)) +#define SUBPIXELS(x) ((TPos)(x) << PIXEL_BITS) +#define FLOOR(x) ((x) & -ONE_PIXEL) +#define CEILING(x) (((x) + ONE_PIXEL - 1) & -ONE_PIXEL) +#define ROUND(x) (((x) + ONE_PIXEL / 2) & -ONE_PIXEL) #if PIXEL_BITS >= 6 -#define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) ) -#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) ) +#define UPSCALE(x) ((x) << (PIXEL_BITS - 6)) +#define DOWNSCALE(x) ((x) >> (PIXEL_BITS - 6)) #else -#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) ) -#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) ) +#define UPSCALE(x) ((x) >> (6 - PIXEL_BITS)) +#define DOWNSCALE(x) ((x) << (6 - PIXEL_BITS)) #endif - - /* Compute `dividend / divisor' and return both its quotient and */ - /* remainder, cast to a specific type. This macro also ensures that */ - /* the remainder is always positive. */ -#define SW_FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \ - SW_FT_BEGIN_STMNT \ - (quotient) = (type)( (dividend) / (divisor) ); \ - (remainder) = (type)( (dividend) % (divisor) ); \ - if ( (remainder) < 0 ) \ - { \ - (quotient)--; \ - (remainder) += (type)(divisor); \ - } \ - SW_FT_END_STMNT - -#ifdef __arm__ - /* Work around a bug specific to GCC which make the compiler fail to */ - /* optimize a division and modulo operation on the same parameters */ - /* into a single call to `__aeabi_idivmod'. See */ - /* */ - /* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 */ +/* Compute `dividend / divisor' and return both its quotient and */ +/* remainder, cast to a specific type. This macro also ensures that */ +/* the remainder is always positive. */ +#define SW_FT_DIV_MOD(type, dividend, divisor, quotient, remainder) \ + SW_FT_BEGIN_STMNT(quotient) = (type)((dividend) / (divisor)); \ + (remainder) = (type)((dividend) % (divisor)); \ + if ((remainder) < 0) { \ + (quotient)--; \ + (remainder) += (type)(divisor); \ + } \ + SW_FT_END_STMNT + +#ifdef __arm__ +/* Work around a bug specific to GCC which make the compiler fail to */ +/* optimize a division and modulo operation on the same parameters */ +/* into a single call to `__aeabi_idivmod'. See */ +/* */ +/* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 */ #undef SW_FT_DIV_MOD -#define SW_FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \ - SW_FT_BEGIN_STMNT \ - (quotient) = (type)( (dividend) / (divisor) ); \ - (remainder) = (type)( (dividend) - (quotient) * (divisor) ); \ - if ( (remainder) < 0 ) \ - { \ - (quotient)--; \ - (remainder) += (type)(divisor); \ - } \ - SW_FT_END_STMNT +#define SW_FT_DIV_MOD(type, dividend, divisor, quotient, remainder) \ + SW_FT_BEGIN_STMNT(quotient) = (type)((dividend) / (divisor)); \ + (remainder) = (type)((dividend) - (quotient) * (divisor)); \ + if ((remainder) < 0) { \ + (quotient)--; \ + (remainder) += (type)(divisor); \ + } \ + SW_FT_END_STMNT #endif /* __arm__ */ - /* These macros speed up repetitive divisions by replacing them */ - /* with multiplications and right shifts. */ -#define SW_FT_UDIVPREP( b ) \ - long b ## _r = (long)( SW_FT_ULONG_MAX >> PIXEL_BITS ) / ( b ) -#define SW_FT_UDIV( a, b ) \ - ( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >> \ - ( sizeof( long ) * SW_FT_CHAR_BIT - PIXEL_BITS ) ) +/* These macros speed up repetitive divisions by replacing them */ +/* with multiplications and right shifts. */ +#define SW_FT_UDIVPREP(b) \ + long b##_r = (long)(SW_FT_ULONG_MAX >> PIXEL_BITS) / (b) +#define SW_FT_UDIV(a, b) \ + (((unsigned long)(a) * (unsigned long)(b##_r)) >> \ + (sizeof(long) * SW_FT_CHAR_BIT - PIXEL_BITS)) +/*************************************************************************/ +/* */ +/* TYPE DEFINITIONS */ +/* */ - /*************************************************************************/ - /* */ - /* TYPE DEFINITIONS */ - /* */ +/* don't change the following types to SW_FT_Int or SW_FT_Pos, since we might */ +/* need to define them to "float" or "double" when experimenting with */ +/* new algorithms */ - /* don't change the following types to SW_FT_Int or SW_FT_Pos, since we might */ - /* need to define them to "float" or "double" when experimenting with */ - /* new algorithms */ +typedef long TCoord; /* integer scanline/pixel coordinate */ +typedef long TPos; /* sub-pixel coordinate */ - typedef long TCoord; /* integer scanline/pixel coordinate */ - typedef long TPos; /* sub-pixel coordinate */ - - /* determine the type used to store cell areas. This normally takes at */ - /* least PIXEL_BITS*2 + 1 bits. On 16-bit systems, we need to use */ - /* `long' instead of `int', otherwise bad things happen */ +/* determine the type used to store cell areas. This normally takes at */ +/* least PIXEL_BITS*2 + 1 bits. On 16-bit systems, we need to use */ +/* `long' instead of `int', otherwise bad things happen */ #if PIXEL_BITS <= 7 - typedef int TArea; +typedef int TArea; #else /* PIXEL_BITS >= 8 */ - /* approximately determine the size of integers using an ANSI-C header */ +/* approximately determine the size of integers using an ANSI-C header */ #if SW_FT_UINT_MAX == 0xFFFFU - typedef long TArea; +typedef long TArea; #else - typedef int TArea; +typedef int TArea; #endif #endif /* PIXEL_BITS >= 8 */ +/* maximum number of gray spans in a call to the span callback */ +#define SW_FT_MAX_GRAY_SPANS 256 - /* maximum number of gray spans in a call to the span callback */ -#define SW_FT_MAX_GRAY_SPANS 256 - - - typedef struct TCell_* PCell; +typedef struct TCell_* PCell; - typedef struct TCell_ - { - TPos x; /* same with gray_TWorker.ex */ - TCoord cover; /* same with gray_TWorker.cover */ - TArea area; - PCell next; +typedef struct TCell_ { + TPos x; /* same with gray_TWorker.ex */ + TCoord cover; /* same with gray_TWorker.cover */ + TArea area; + PCell next; - } TCell; +} TCell; - -#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */ - /* We disable the warning `structure was padded due to */ - /* __declspec(align())' in order to compile cleanly with */ - /* the maximum level of warnings. */ -#pragma warning( push ) -#pragma warning( disable : 4324 ) +#if defined(_MSC_VER) /* Visual C++ (and Intel C++) */ +/* We disable the warning `structure was padded due to */ +/* __declspec(align())' in order to compile cleanly with */ +/* the maximum level of warnings. */ +#pragma warning(push) +#pragma warning(disable : 4324) #endif /* _MSC_VER */ - typedef struct gray_TWorker_ - { - TCoord ex, ey; - TPos min_ex, max_ex; - TPos min_ey, max_ey; - TPos count_ex, count_ey; - - TArea area; - TCoord cover; - int invalid; +typedef struct gray_TWorker_ { + TCoord ex, ey; + TPos min_ex, max_ex; + TPos min_ey, max_ey; + TPos count_ex, count_ey; - PCell cells; - SW_FT_PtrDist max_cells; - SW_FT_PtrDist num_cells; + TArea area; + TCoord cover; + int invalid; - TPos x, y; + PCell cells; + SW_FT_PtrDist max_cells; + SW_FT_PtrDist num_cells; + TPos x, y; - SW_FT_Vector bez_stack[32 * 3 + 1]; - int lev_stack[32]; + SW_FT_Vector bez_stack[32 * 3 + 1]; + int lev_stack[32]; - SW_FT_Outline outline; - SW_FT_BBox clip_box; + SW_FT_Outline outline; + SW_FT_BBox clip_box; - SW_FT_Span gray_spans[SW_FT_MAX_GRAY_SPANS]; - int num_gray_spans; + SW_FT_Span gray_spans[SW_FT_MAX_GRAY_SPANS]; + int num_gray_spans; - SW_FT_Raster_Span_Func render_span; - void* render_span_data; + SW_FT_Raster_Span_Func render_span; + void* render_span_data; - int band_size; - int band_shoot; + int band_size; + int band_shoot; - ft_jmp_buf jump_buffer; + ft_jmp_buf jump_buffer; - void* buffer; - long buffer_size; + void* buffer; + long buffer_size; - PCell* ycells; - TPos ycount; + PCell* ycells; + TPos ycount; - } gray_TWorker, *gray_PWorker; +} gray_TWorker, *gray_PWorker; -#if defined( _MSC_VER ) -#pragma warning( pop ) +#if defined(_MSC_VER) +#pragma warning(pop) #endif - #ifndef SW_FT_STATIC_RASTER -#define ras (*worker) +#define ras (*worker) #else - static gray_TWorker ras; +static gray_TWorker ras; #endif +typedef struct gray_TRaster_ { + void* memory; - typedef struct gray_TRaster_ - { - void* memory; - - } gray_TRaster, *gray_PRaster; - +} gray_TRaster, *gray_PRaster; - - /*************************************************************************/ - /* */ - /* Initialize the cells table. */ - /* */ - static void - gray_init_cells( RAS_ARG_ void* buffer, - long byte_size ) - { - ras.buffer = buffer; +/*************************************************************************/ +/* */ +/* Initialize the cells table. */ +/* */ +static void gray_init_cells(RAS_ARG_ void* buffer, long byte_size) +{ + ras.buffer = buffer; ras.buffer_size = byte_size; - ras.ycells = (PCell*) buffer; - ras.cells = NULL; - ras.max_cells = 0; - ras.num_cells = 0; - ras.area = 0; - ras.cover = 0; - ras.invalid = 1; - } - - - /*************************************************************************/ - /* */ - /* Compute the outline bounding box. */ - /* */ - static void - gray_compute_cbox( RAS_ARG ) - { - SW_FT_Outline* outline = &ras.outline; - SW_FT_Vector* vec = outline->points; - SW_FT_Vector* limit = vec + outline->n_points; - - - if ( outline->n_points <= 0 ) - { - ras.min_ex = ras.max_ex = 0; - ras.min_ey = ras.max_ey = 0; - return; + ras.ycells = (PCell*)buffer; + ras.cells = NULL; + ras.max_cells = 0; + ras.num_cells = 0; + ras.area = 0; + ras.cover = 0; + ras.invalid = 1; +} + +/*************************************************************************/ +/* */ +/* Compute the outline bounding box. */ +/* */ +static void gray_compute_cbox(RAS_ARG) +{ + SW_FT_Outline* outline = &ras.outline; + SW_FT_Vector* vec = outline->points; + SW_FT_Vector* limit = vec + outline->n_points; + + if (outline->n_points <= 0) { + ras.min_ex = ras.max_ex = 0; + ras.min_ey = ras.max_ey = 0; + return; } ras.min_ex = ras.max_ex = vec->x; @@ -440,91 +384,74 @@ typedef struct SW_FT_Outline_Funcs_ vec++; - for ( ; vec < limit; vec++ ) - { - TPos x = vec->x; - TPos y = vec->y; - + for (; vec < limit; vec++) { + TPos x = vec->x; + TPos y = vec->y; - if ( x < ras.min_ex ) ras.min_ex = x; - if ( x > ras.max_ex ) ras.max_ex = x; - if ( y < ras.min_ey ) ras.min_ey = y; - if ( y > ras.max_ey ) ras.max_ey = y; + if (x < ras.min_ex) ras.min_ex = x; + if (x > ras.max_ex) ras.max_ex = x; + if (y < ras.min_ey) ras.min_ey = y; + if (y > ras.max_ey) ras.max_ey = y; } /* truncate the bounding box to integer pixels */ ras.min_ex = ras.min_ex >> 6; ras.min_ey = ras.min_ey >> 6; - ras.max_ex = ( ras.max_ex + 63 ) >> 6; - ras.max_ey = ( ras.max_ey + 63 ) >> 6; - } - - - /*************************************************************************/ - /* */ - /* Record the current cell in the table. */ - /* */ - static PCell - gray_find_cell( RAS_ARG ) - { - PCell *pcell, cell; - TPos x = ras.ex; - + ras.max_ex = (ras.max_ex + 63) >> 6; + ras.max_ey = (ras.max_ey + 63) >> 6; +} + +/*************************************************************************/ +/* */ +/* Record the current cell in the table. */ +/* */ +static PCell gray_find_cell(RAS_ARG) +{ + PCell *pcell, cell; + TPos x = ras.ex; - if ( x > ras.count_ex ) - x = ras.count_ex; + if (x > ras.count_ex) x = ras.count_ex; pcell = &ras.ycells[ras.ey]; - for (;;) - { - cell = *pcell; - if ( cell == NULL || cell->x > x ) - break; + for (;;) { + cell = *pcell; + if (cell == NULL || cell->x > x) break; - if ( cell->x == x ) - goto Exit; + if (cell->x == x) goto Exit; - pcell = &cell->next; + pcell = &cell->next; } - if ( ras.num_cells >= ras.max_cells ) - ft_longjmp( ras.jump_buffer, 1 ); + if (ras.num_cells >= ras.max_cells) ft_longjmp(ras.jump_buffer, 1); - cell = ras.cells + ras.num_cells++; - cell->x = x; - cell->area = 0; + cell = ras.cells + ras.num_cells++; + cell->x = x; + cell->area = 0; cell->cover = 0; - cell->next = *pcell; - *pcell = cell; + cell->next = *pcell; + *pcell = cell; - Exit: +Exit: return cell; - } - - - static void - gray_record_cell( RAS_ARG ) - { - if ( ras.area | ras.cover ) - { - PCell cell = gray_find_cell( RAS_VAR ); +} +static void gray_record_cell(RAS_ARG) +{ + if (ras.area | ras.cover) { + PCell cell = gray_find_cell(RAS_VAR); - cell->area += ras.area; - cell->cover += ras.cover; + cell->area += ras.area; + cell->cover += ras.cover; } - } - +} - /*************************************************************************/ - /* */ - /* Set the current cell to a new position. */ - /* */ - static void - gray_set_cell( RAS_ARG_ TCoord ex, - TCoord ey ) - { +/*************************************************************************/ +/* */ +/* Set the current cell to a new position. */ +/* */ +static void gray_set_cell(RAS_ARG_ TCoord ex, TCoord ey) +{ /* Move the cell pointer to a new position. We set the `invalid' */ /* flag to indicate that the cell isn't part of those we're interested */ /* in during the render phase. This means that: */ @@ -539,326 +466,286 @@ typedef struct SW_FT_Outline_Funcs_ /* min_ex - 1 horizontal position. */ ey -= ras.min_ey; - if ( ex > ras.max_ex ) - ex = ras.max_ex; + if (ex > ras.max_ex) ex = ras.max_ex; ex -= ras.min_ex; - if ( ex < 0 ) - ex = -1; + if (ex < 0) ex = -1; /* are we moving to a different cell ? */ - if ( ex != ras.ex || ey != ras.ey ) - { - /* record the current one if it is valid */ - if ( !ras.invalid ) - gray_record_cell( RAS_VAR ); - - ras.area = 0; - ras.cover = 0; - ras.ex = ex; - ras.ey = ey; + if (ex != ras.ex || ey != ras.ey) { + /* record the current one if it is valid */ + if (!ras.invalid) gray_record_cell(RAS_VAR); + + ras.area = 0; + ras.cover = 0; + ras.ex = ex; + ras.ey = ey; } - ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey || - ex >= ras.count_ex ); - } - - - /*************************************************************************/ - /* */ - /* Start a new contour at a given cell. */ - /* */ - static void - gray_start_cell( RAS_ARG_ TCoord ex, - TCoord ey ) - { - if ( ex > ras.max_ex ) - ex = (TCoord)( ras.max_ex ); - - if ( ex < ras.min_ex ) - ex = (TCoord)( ras.min_ex - 1 ); - - ras.area = 0; - ras.cover = 0; - ras.ex = ex - ras.min_ex; - ras.ey = ey - ras.min_ey; - ras.invalid = 0; + ras.invalid = + ((unsigned)ey >= (unsigned)ras.count_ey || ex >= ras.count_ex); +} - gray_set_cell( RAS_VAR_ ex, ey ); - } +/*************************************************************************/ +/* */ +/* Start a new contour at a given cell. */ +/* */ +static void gray_start_cell(RAS_ARG_ TCoord ex, TCoord ey) +{ + if (ex > ras.max_ex) ex = (TCoord)(ras.max_ex); - /*************************************************************************/ - /* */ - /* Render a straight line across multiple cells in any direction. */ - /* */ - static void - gray_render_line( RAS_ARG_ TPos to_x, - TPos to_y ) - { - TPos dx, dy, fx1, fy1, fx2, fy2; - TCoord ex1, ex2, ey1, ey2; + if (ex < ras.min_ex) ex = (TCoord)(ras.min_ex - 1); + ras.area = 0; + ras.cover = 0; + ras.ex = ex - ras.min_ex; + ras.ey = ey - ras.min_ey; + ras.invalid = 0; - ex1 = TRUNC( ras.x ); - ex2 = TRUNC( to_x ); - ey1 = TRUNC( ras.y ); - ey2 = TRUNC( to_y ); + gray_set_cell(RAS_VAR_ ex, ey); +} + +/*************************************************************************/ +/* */ +/* Render a straight line across multiple cells in any direction. */ +/* */ +static void gray_render_line(RAS_ARG_ TPos to_x, TPos to_y) +{ + TPos dx, dy, fx1, fy1, fx2, fy2; + TCoord ex1, ex2, ey1, ey2; + + ex1 = TRUNC(ras.x); + ex2 = TRUNC(to_x); + ey1 = TRUNC(ras.y); + ey2 = TRUNC(to_y); /* perform vertical clipping */ - if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) || - ( ey1 < ras.min_ey && ey2 < ras.min_ey ) ) - goto End; + if ((ey1 >= ras.max_ey && ey2 >= ras.max_ey) || + (ey1 < ras.min_ey && ey2 < ras.min_ey)) + goto End; dx = to_x - ras.x; dy = to_y - ras.y; - fx1 = ras.x - SUBPIXELS( ex1 ); - fy1 = ras.y - SUBPIXELS( ey1 ); + fx1 = ras.x - SUBPIXELS(ex1); + fy1 = ras.y - SUBPIXELS(ey1); - if ( ex1 == ex2 && ey1 == ey2 ) /* inside one cell */ - ; - else if ( dy == 0 ) /* ex1 != ex2 */ /* any horizontal line */ + if (ex1 == ex2 && ey1 == ey2) /* inside one cell */ + ; + else if (dy == 0) /* ex1 != ex2 */ /* any horizontal line */ { - ex1 = ex2; - gray_set_cell( RAS_VAR_ ex1, ey1 ); - } - else if ( dx == 0 ) - { - if ( dy > 0 ) /* vertical line up */ - do - { - fy2 = ONE_PIXEL; - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * fx1 * 2; - fy1 = 0; - ey1++; - gray_set_cell( RAS_VAR_ ex1, ey1 ); - } while ( ey1 != ey2 ); - else /* vertical line down */ - do - { - fy2 = 0; - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * fx1 * 2; - fy1 = ONE_PIXEL; - ey1--; - gray_set_cell( RAS_VAR_ ex1, ey1 ); - } while ( ey1 != ey2 ); - } - else /* any other line */ + ex1 = ex2; + gray_set_cell(RAS_VAR_ ex1, ey1); + } else if (dx == 0) { + if (dy > 0) /* vertical line up */ + do { + fy2 = ONE_PIXEL; + ras.cover += (fy2 - fy1); + ras.area += (fy2 - fy1) * fx1 * 2; + fy1 = 0; + ey1++; + gray_set_cell(RAS_VAR_ ex1, ey1); + } while (ey1 != ey2); + else /* vertical line down */ + do { + fy2 = 0; + ras.cover += (fy2 - fy1); + ras.area += (fy2 - fy1) * fx1 * 2; + fy1 = ONE_PIXEL; + ey1--; + gray_set_cell(RAS_VAR_ ex1, ey1); + } while (ey1 != ey2); + } else /* any other line */ { - TArea prod = dx * fy1 - dy * fx1; - SW_FT_UDIVPREP( dx ); - SW_FT_UDIVPREP( dy ); - - - /* The fundamental value `prod' determines which side and the */ - /* exact coordinate where the line exits current cell. It is */ - /* also easily updated when moving from one cell to the next. */ - do - { - if ( prod <= 0 && - prod - dx * ONE_PIXEL > 0 ) /* left */ - { - fx2 = 0; - fy2 = (TPos)SW_FT_UDIV( -prod, -dx ); - prod -= dy * ONE_PIXEL; - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); - fx1 = ONE_PIXEL; - fy1 = fy2; - ex1--; - } - else if ( prod - dx * ONE_PIXEL <= 0 && - prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 ) /* up */ - { - prod -= dx * ONE_PIXEL; - fx2 = (TPos)SW_FT_UDIV( -prod, dy ); - fy2 = ONE_PIXEL; - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); - fx1 = fx2; - fy1 = 0; - ey1++; - } - else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 && - prod + dy * ONE_PIXEL >= 0 ) /* right */ - { - prod += dy * ONE_PIXEL; - fx2 = ONE_PIXEL; - fy2 = (TPos)SW_FT_UDIV( prod, dx ); - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); - fx1 = 0; - fy1 = fy2; - ex1++; - } - else /* ( prod + dy * ONE_PIXEL < 0 && - prod > 0 ) down */ - { - fx2 = (TPos)SW_FT_UDIV( prod, -dy ); - fy2 = 0; - prod += dx * ONE_PIXEL; - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); - fx1 = fx2; - fy1 = ONE_PIXEL; - ey1--; - } + TArea prod = dx * fy1 - dy * fx1; + SW_FT_UDIVPREP(dx); + SW_FT_UDIVPREP(dy); + + /* The fundamental value `prod' determines which side and the */ + /* exact coordinate where the line exits current cell. It is */ + /* also easily updated when moving from one cell to the next. */ + do { + if (prod <= 0 && prod - dx * ONE_PIXEL > 0) /* left */ + { + fx2 = 0; + fy2 = (TPos)SW_FT_UDIV(-prod, -dx); + prod -= dy * ONE_PIXEL; + ras.cover += (fy2 - fy1); + ras.area += (fy2 - fy1) * (fx1 + fx2); + fx1 = ONE_PIXEL; + fy1 = fy2; + ex1--; + } else if (prod - dx * ONE_PIXEL <= 0 && + prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0) /* up */ + { + prod -= dx * ONE_PIXEL; + fx2 = (TPos)SW_FT_UDIV(-prod, dy); + fy2 = ONE_PIXEL; + ras.cover += (fy2 - fy1); + ras.area += (fy2 - fy1) * (fx1 + fx2); + fx1 = fx2; + fy1 = 0; + ey1++; + } else if (prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 && + prod + dy * ONE_PIXEL >= 0) /* right */ + { + prod += dy * ONE_PIXEL; + fx2 = ONE_PIXEL; + fy2 = (TPos)SW_FT_UDIV(prod, dx); + ras.cover += (fy2 - fy1); + ras.area += (fy2 - fy1) * (fx1 + fx2); + fx1 = 0; + fy1 = fy2; + ex1++; + } else /* ( prod + dy * ONE_PIXEL < 0 && + prod > 0 ) down */ + { + fx2 = (TPos)SW_FT_UDIV(prod, -dy); + fy2 = 0; + prod += dx * ONE_PIXEL; + ras.cover += (fy2 - fy1); + ras.area += (fy2 - fy1) * (fx1 + fx2); + fx1 = fx2; + fy1 = ONE_PIXEL; + ey1--; + } - gray_set_cell( RAS_VAR_ ex1, ey1 ); - } while ( ex1 != ex2 || ey1 != ey2 ); + gray_set_cell(RAS_VAR_ ex1, ey1); + } while (ex1 != ex2 || ey1 != ey2); } - fx2 = to_x - SUBPIXELS( ex2 ); - fy2 = to_y - SUBPIXELS( ey2 ); + fx2 = to_x - SUBPIXELS(ex2); + fy2 = to_y - SUBPIXELS(ey2); - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); + ras.cover += (fy2 - fy1); + ras.area += (fy2 - fy1) * (fx1 + fx2); - End: - ras.x = to_x; - ras.y = to_y; - } - - static void - gray_split_conic( SW_FT_Vector* base ) - { - TPos a, b; +End: + ras.x = to_x; + ras.y = to_y; +} +static void gray_split_conic(SW_FT_Vector* base) +{ + TPos a, b; base[4].x = base[2].x; b = base[1].x; - a = base[3].x = ( base[2].x + b ) / 2; - b = base[1].x = ( base[0].x + b ) / 2; - base[2].x = ( a + b ) / 2; + a = base[3].x = (base[2].x + b) / 2; + b = base[1].x = (base[0].x + b) / 2; + base[2].x = (a + b) / 2; base[4].y = base[2].y; b = base[1].y; - a = base[3].y = ( base[2].y + b ) / 2; - b = base[1].y = ( base[0].y + b ) / 2; - base[2].y = ( a + b ) / 2; - } - - - static void - gray_render_conic( RAS_ARG_ const SW_FT_Vector* control, - const SW_FT_Vector* to ) - { - TPos dx, dy; - TPos min, max, y; - int top, level; - int* levels; - SW_FT_Vector* arc; + a = base[3].y = (base[2].y + b) / 2; + b = base[1].y = (base[0].y + b) / 2; + base[2].y = (a + b) / 2; +} +static void gray_render_conic(RAS_ARG_ const SW_FT_Vector* control, + const SW_FT_Vector* to) +{ + TPos dx, dy; + TPos min, max, y; + int top, level; + int* levels; + SW_FT_Vector* arc; levels = ras.lev_stack; - arc = ras.bez_stack; - arc[0].x = UPSCALE( to->x ); - arc[0].y = UPSCALE( to->y ); - arc[1].x = UPSCALE( control->x ); - arc[1].y = UPSCALE( control->y ); + arc = ras.bez_stack; + arc[0].x = UPSCALE(to->x); + arc[0].y = UPSCALE(to->y); + arc[1].x = UPSCALE(control->x); + arc[1].y = UPSCALE(control->y); arc[2].x = ras.x; arc[2].y = ras.y; - top = 0; + top = 0; - dx = SW_FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x ); - dy = SW_FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y ); - if ( dx < dy ) - dx = dy; + dx = SW_FT_ABS(arc[2].x + arc[0].x - 2 * arc[1].x); + dy = SW_FT_ABS(arc[2].y + arc[0].y - 2 * arc[1].y); + if (dx < dy) dx = dy; - if ( dx < ONE_PIXEL / 4 ) - goto Draw; + if (dx < ONE_PIXEL / 4) goto Draw; /* short-cut the arc that crosses the current band */ min = max = arc[0].y; y = arc[1].y; - if ( y < min ) min = y; - if ( y > max ) max = y; + if (y < min) min = y; + if (y > max) max = y; y = arc[2].y; - if ( y < min ) min = y; - if ( y > max ) max = y; + if (y < min) min = y; + if (y > max) max = y; - if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey ) - goto Draw; + if (TRUNC(min) >= ras.max_ey || TRUNC(max) < ras.min_ey) goto Draw; level = 0; - do - { - dx >>= 2; - level++; - } while ( dx > ONE_PIXEL / 4 ); + do { + dx >>= 2; + level++; + } while (dx > ONE_PIXEL / 4); levels[0] = level; - do - { - level = levels[top]; - if ( level > 0 ) - { - gray_split_conic( arc ); - arc += 2; - top++; - levels[top] = levels[top - 1] = level - 1; - continue; - } + do { + level = levels[top]; + if (level > 0) { + gray_split_conic(arc); + arc += 2; + top++; + levels[top] = levels[top - 1] = level - 1; + continue; + } Draw: - gray_render_line( RAS_VAR_ arc[0].x, arc[0].y ); - top--; - arc -= 2; - - } while ( top >= 0 ); - } + gray_render_line(RAS_VAR_ arc[0].x, arc[0].y); + top--; + arc -= 2; + } while (top >= 0); +} - static void - gray_split_cubic( SW_FT_Vector* base ) - { - TPos a, b, c, d; - +static void gray_split_cubic(SW_FT_Vector* base) +{ + TPos a, b, c, d; base[6].x = base[3].x; c = base[1].x; d = base[2].x; - base[1].x = a = ( base[0].x + c ) / 2; - base[5].x = b = ( base[3].x + d ) / 2; - c = ( c + d ) / 2; - base[2].x = a = ( a + c ) / 2; - base[4].x = b = ( b + c ) / 2; - base[3].x = ( a + b ) / 2; + base[1].x = a = (base[0].x + c) / 2; + base[5].x = b = (base[3].x + d) / 2; + c = (c + d) / 2; + base[2].x = a = (a + c) / 2; + base[4].x = b = (b + c) / 2; + base[3].x = (a + b) / 2; base[6].y = base[3].y; c = base[1].y; d = base[2].y; - base[1].y = a = ( base[0].y + c ) / 2; - base[5].y = b = ( base[3].y + d ) / 2; - c = ( c + d ) / 2; - base[2].y = a = ( a + c ) / 2; - base[4].y = b = ( b + c ) / 2; - base[3].y = ( a + b ) / 2; - } - - - static void - gray_render_cubic( RAS_ARG_ const SW_FT_Vector* control1, - const SW_FT_Vector* control2, - const SW_FT_Vector* to ) - { - SW_FT_Vector* arc; - TPos min, max, y; - - - arc = ras.bez_stack; - arc[0].x = UPSCALE( to->x ); - arc[0].y = UPSCALE( to->y ); - arc[1].x = UPSCALE( control2->x ); - arc[1].y = UPSCALE( control2->y ); - arc[2].x = UPSCALE( control1->x ); - arc[2].y = UPSCALE( control1->y ); + base[1].y = a = (base[0].y + c) / 2; + base[5].y = b = (base[3].y + d) / 2; + c = (c + d) / 2; + base[2].y = a = (a + c) / 2; + base[4].y = b = (b + c) / 2; + base[3].y = (a + b) / 2; +} + +static void gray_render_cubic(RAS_ARG_ const SW_FT_Vector* control1, + const SW_FT_Vector* control2, + const SW_FT_Vector* to) +{ + SW_FT_Vector* arc; + TPos min, max, y; + + arc = ras.bez_stack; + arc[0].x = UPSCALE(to->x); + arc[0].y = UPSCALE(to->y); + arc[1].x = UPSCALE(control2->x); + arc[1].y = UPSCALE(control2->y); + arc[2].x = UPSCALE(control1->x); + arc[2].y = UPSCALE(control1->y); arc[3].x = ras.x; arc[3].y = ras.y; @@ -866,808 +753,684 @@ typedef struct SW_FT_Outline_Funcs_ min = max = arc[0].y; y = arc[1].y; - if ( y < min ) - min = y; - if ( y > max ) - max = y; + if (y < min) min = y; + if (y > max) max = y; y = arc[2].y; - if ( y < min ) - min = y; - if ( y > max ) - max = y; + if (y < min) min = y; + if (y > max) max = y; y = arc[3].y; - if ( y < min ) - min = y; - if ( y > max ) - max = y; - - if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey ) - goto Draw; + if (y < min) min = y; + if (y > max) max = y; - for (;;) - { - /* Decide whether to split or draw. See `Rapid Termination */ - /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */ - /* F. Hain, at */ - /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */ + if (TRUNC(min) >= ras.max_ey || TRUNC(max) < ras.min_ey) goto Draw; - { - TPos dx, dy, dx_, dy_; - TPos dx1, dy1, dx2, dy2; - TPos L, s, s_limit; + for (;;) { + /* Decide whether to split or draw. See `Rapid Termination */ + /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */ + /* F. Hain, at */ + /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf + */ + { + TPos dx, dy, dx_, dy_; + TPos dx1, dy1, dx2, dy2; + TPos L, s, s_limit; - /* dx and dy are x and y components of the P0-P3 chord vector. */ - dx = dx_ = arc[3].x - arc[0].x; - dy = dy_ = arc[3].y - arc[0].y; + /* dx and dy are x and y components of the P0-P3 chord vector. */ + dx = dx_ = arc[3].x - arc[0].x; + dy = dy_ = arc[3].y - arc[0].y; - L = SW_FT_HYPOT( dx_, dy_ ); + L = SW_FT_HYPOT(dx_, dy_); - /* Avoid possible arithmetic overflow below by splitting. */ - if ( L > 32767 ) - goto Split; + /* Avoid possible arithmetic overflow below by splitting. */ + if (L > 32767) goto Split; - /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */ - s_limit = L * (TPos)( ONE_PIXEL / 6 ); + /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */ + s_limit = L * (TPos)(ONE_PIXEL / 6); - /* s is L * the perpendicular distance from P1 to the line P0-P3. */ - dx1 = arc[1].x - arc[0].x; - dy1 = arc[1].y - arc[0].y; - s = SW_FT_ABS( dy * dx1 - dx * dy1 ); + /* s is L * the perpendicular distance from P1 to the line P0-P3. */ + dx1 = arc[1].x - arc[0].x; + dy1 = arc[1].y - arc[0].y; + s = SW_FT_ABS(dy * dx1 - dx * dy1); - if ( s > s_limit ) - goto Split; + if (s > s_limit) goto Split; - /* s is L * the perpendicular distance from P2 to the line P0-P3. */ - dx2 = arc[2].x - arc[0].x; - dy2 = arc[2].y - arc[0].y; - s = SW_FT_ABS( dy * dx2 - dx * dy2 ); + /* s is L * the perpendicular distance from P2 to the line P0-P3. */ + dx2 = arc[2].x - arc[0].x; + dy2 = arc[2].y - arc[0].y; + s = SW_FT_ABS(dy * dx2 - dx * dy2); - if ( s > s_limit ) - goto Split; + if (s > s_limit) goto Split; - /* Split super curvy segments where the off points are so far - from the chord that the angles P0-P1-P3 or P0-P2-P3 become - acute as detected by appropriate dot products. */ - if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 || - dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 ) - goto Split; + /* Split super curvy segments where the off points are so far + from the chord that the angles P0-P1-P3 or P0-P2-P3 become + acute as detected by appropriate dot products. */ + if (dx1 * (dx1 - dx) + dy1 * (dy1 - dy) > 0 || + dx2 * (dx2 - dx) + dy2 * (dy2 - dy) > 0) + goto Split; - /* No reason to split. */ - goto Draw; - } + /* No reason to split. */ + goto Draw; + } Split: - gray_split_cubic( arc ); - arc += 3; - continue; + gray_split_cubic(arc); + arc += 3; + continue; Draw: - gray_render_line( RAS_VAR_ arc[0].x, arc[0].y ); + gray_render_line(RAS_VAR_ arc[0].x, arc[0].y); - if ( arc == ras.bez_stack ) - return; + if (arc == ras.bez_stack) return; - arc -= 3; + arc -= 3; } - } - - - static int - gray_move_to( const SW_FT_Vector* to, - gray_PWorker worker ) - { - TPos x, y; +} +static int gray_move_to(const SW_FT_Vector* to, gray_PWorker worker) +{ + TPos x, y; /* record current cell, if any */ - if ( !ras.invalid ) - gray_record_cell( RAS_VAR ); + if (!ras.invalid) gray_record_cell(RAS_VAR); /* start to a new position */ - x = UPSCALE( to->x ); - y = UPSCALE( to->y ); + x = UPSCALE(to->x); + y = UPSCALE(to->y); - gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) ); + gray_start_cell(RAS_VAR_ TRUNC(x), TRUNC(y)); worker->x = x; worker->y = y; return 0; - } - +} - static int - gray_line_to( const SW_FT_Vector* to, - gray_PWorker worker ) - { - gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) ); +static int gray_line_to(const SW_FT_Vector* to, gray_PWorker worker) +{ + gray_render_line(RAS_VAR_ UPSCALE(to->x), UPSCALE(to->y)); return 0; - } - +} - static int - gray_conic_to( const SW_FT_Vector* control, - const SW_FT_Vector* to, - gray_PWorker worker ) - { - gray_render_conic( RAS_VAR_ control, to ); +static int gray_conic_to(const SW_FT_Vector* control, const SW_FT_Vector* to, + gray_PWorker worker) +{ + gray_render_conic(RAS_VAR_ control, to); return 0; - } +} - - static int - gray_cubic_to( const SW_FT_Vector* control1, - const SW_FT_Vector* control2, - const SW_FT_Vector* to, - gray_PWorker worker ) - { - gray_render_cubic( RAS_VAR_ control1, control2, to ); +static int gray_cubic_to(const SW_FT_Vector* control1, + const SW_FT_Vector* control2, const SW_FT_Vector* to, + gray_PWorker worker) +{ + gray_render_cubic(RAS_VAR_ control1, control2, to); return 0; - } - - - static void - gray_hline( RAS_ARG_ TCoord x, - TCoord y, - TPos area, - TCoord acount ) - { - int coverage; +} +static void gray_hline(RAS_ARG_ TCoord x, TCoord y, TPos area, TCoord acount) +{ + int coverage; /* compute the coverage line's coverage, depending on the */ /* outline fill rule */ /* */ /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */ /* */ - coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) ); - /* use range 0..256 */ - if ( coverage < 0 ) - coverage = -coverage; - - if ( ras.outline.flags & SW_FT_OUTLINE_EVEN_ODD_FILL ) - { - coverage &= 511; - - if ( coverage > 256 ) - coverage = 512 - coverage; - else if ( coverage == 256 ) - coverage = 255; - } - else - { - /* normal non-zero winding rule */ - if ( coverage >= 256 ) - coverage = 255; + coverage = (int)(area >> (PIXEL_BITS * 2 + 1 - 8)); + /* use range 0..256 */ + if (coverage < 0) coverage = -coverage; + + if (ras.outline.flags & SW_FT_OUTLINE_EVEN_ODD_FILL) { + coverage &= 511; + + if (coverage > 256) + coverage = 512 - coverage; + else if (coverage == 256) + coverage = 255; + } else { + /* normal non-zero winding rule */ + if (coverage >= 256) coverage = 255; } y += (TCoord)ras.min_ey; x += (TCoord)ras.min_ex; /* SW_FT_Span.x is a 16-bit short, so limit our coordinates appropriately */ - if ( x >= 32767 ) - x = 32767; + if (x >= 32767) x = 32767; /* SW_FT_Span.y is an integer, so limit our coordinates appropriately */ - if ( y >= SW_FT_INT_MAX ) - y = SW_FT_INT_MAX; - - if ( coverage ) - { - SW_FT_Span* span; - int count; - - - /* see whether we can add this span to the current list */ - count = ras.num_gray_spans; - span = ras.gray_spans + count - 1; - if ( count > 0 && - span->y == y && - (int)span->x + span->len == (int)x && - span->coverage == coverage ) - { - span->len = (unsigned short)( span->len + acount ); - return; - } - - if ( count >= SW_FT_MAX_GRAY_SPANS ) - { - if ( ras.render_span && count > 0 ) - ras.render_span(count, ras.gray_spans, - ras.render_span_data ); + if (y >= SW_FT_INT_MAX) y = SW_FT_INT_MAX; + + if (coverage) { + SW_FT_Span* span; + int count; + + /* see whether we can add this span to the current list */ + count = ras.num_gray_spans; + span = ras.gray_spans + count - 1; + if (count > 0 && span->y == y && (int)span->x + span->len == (int)x && + span->coverage == coverage) { + span->len = (unsigned short)(span->len + acount); + return; + } - #ifdef DEBUG_GRAYS + if (count >= SW_FT_MAX_GRAY_SPANS) { + if (ras.render_span && count > 0) + ras.render_span(count, ras.gray_spans, ras.render_span_data); - if ( 1 ) - { - int n; +#ifdef DEBUG_GRAYS + if (1) { + int n; - fprintf( stderr, "count = %3d ", count ); - span = ras.gray_spans; - for ( n = 0; n < count; n++, span++ ) - fprintf( stderr, "[%d , %d..%d] : %d ", - span->y, span->x, span->x + span->len - 1, span->coverage ); - fprintf( stderr, "\n" ); - } + fprintf(stderr, "count = %3d ", count); + span = ras.gray_spans; + for (n = 0; n < count; n++, span++) + fprintf(stderr, "[%d , %d..%d] : %d ", span->y, span->x, + span->x + span->len - 1, span->coverage); + fprintf(stderr, "\n"); + } - #endif /* DEBUG_GRAYS */ +#endif /* DEBUG_GRAYS */ - ras.num_gray_spans = 0; + ras.num_gray_spans = 0; - span = ras.gray_spans; - } - else - span++; + span = ras.gray_spans; + } else + span++; - /* add a gray span to the current list */ - span->x = (short)x; - span->y = (short)y; - span->len = (unsigned short)acount; - span->coverage = (unsigned char)coverage; + /* add a gray span to the current list */ + span->x = (short)x; + span->y = (short)y; + span->len = (unsigned short)acount; + span->coverage = (unsigned char)coverage; - ras.num_gray_spans++; + ras.num_gray_spans++; } - } +} - static void - gray_sweep( RAS_ARG) - { - int yindex; +static void gray_sweep(RAS_ARG) +{ + int yindex; - if ( ras.num_cells == 0 ) - return; + if (ras.num_cells == 0) return; ras.num_gray_spans = 0; - for ( yindex = 0; yindex < ras.ycount; yindex++ ) - { - PCell cell = ras.ycells[yindex]; - TCoord cover = 0; - TCoord x = 0; - + for (yindex = 0; yindex < ras.ycount; yindex++) { + PCell cell = ras.ycells[yindex]; + TCoord cover = 0; + TCoord x = 0; - for ( ; cell != NULL; cell = cell->next ) - { - TPos area; + for (; cell != NULL; cell = cell->next) { + TPos area; + if (cell->x > x && cover != 0) + gray_hline(RAS_VAR_ x, yindex, cover * (ONE_PIXEL * 2), + cell->x - x); - if ( cell->x > x && cover != 0 ) - gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ), - cell->x - x ); + cover += cell->cover; + area = cover * (ONE_PIXEL * 2) - cell->area; - cover += cell->cover; - area = cover * ( ONE_PIXEL * 2 ) - cell->area; + if (area != 0 && cell->x >= 0) + gray_hline(RAS_VAR_ cell->x, yindex, area, 1); - if ( area != 0 && cell->x >= 0 ) - gray_hline( RAS_VAR_ cell->x, yindex, area, 1 ); - - x = cell->x + 1; - } + x = cell->x + 1; + } - if ( cover != 0 ) - gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ), - ras.count_ex - x ); + if (cover != 0) + gray_hline(RAS_VAR_ x, yindex, cover * (ONE_PIXEL * 2), + ras.count_ex - x); } - if ( ras.render_span && ras.num_gray_spans > 0 ) - ras.render_span(ras.num_gray_spans, - ras.gray_spans, ras.render_span_data ); - } - - - /*************************************************************************/ - /* */ - /* The following function should only compile in stand-alone mode, */ - /* i.e., when building this component without the rest of FreeType. */ - /* */ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* */ - /* SW_FT_Outline_Decompose */ - /* */ - /* */ - /* Walk over an outline's structure to decompose it into individual */ - /* segments and Bézier arcs. This function is also able to emit */ - /* `move to' and `close to' operations to indicate the start and end */ - /* of new contours in the outline. */ - /* */ - /* */ - /* outline :: A pointer to the source target. */ - /* */ - /* func_interface :: A table of `emitters', i.e., function pointers */ - /* called during decomposition to indicate path */ - /* operations. */ - /* */ - /* */ - /* user :: A typeless pointer which is passed to each */ - /* emitter during the decomposition. It can be */ - /* used to store the state during the */ - /* decomposition. */ - /* */ - /* */ - /* Error code. 0 means success. */ - /* */ - static int - SW_FT_Outline_Decompose( const SW_FT_Outline* outline, - const SW_FT_Outline_Funcs* func_interface, - void* user ) - { + if (ras.render_span && ras.num_gray_spans > 0) + ras.render_span(ras.num_gray_spans, ras.gray_spans, + ras.render_span_data); +} + +/*************************************************************************/ +/* */ +/* The following function should only compile in stand-alone mode, */ +/* i.e., when building this component without the rest of FreeType. */ +/* */ +/*************************************************************************/ + +/*************************************************************************/ +/* */ +/* */ +/* SW_FT_Outline_Decompose */ +/* */ +/* */ +/* Walk over an outline's structure to decompose it into individual */ +/* segments and Bézier arcs. This function is also able to emit */ +/* `move to' and `close to' operations to indicate the start and end */ +/* of new contours in the outline. */ +/* */ +/* */ +/* outline :: A pointer to the source target. */ +/* */ +/* func_interface :: A table of `emitters', i.e., function pointers */ +/* called during decomposition to indicate path */ +/* operations. */ +/* */ +/* */ +/* user :: A typeless pointer which is passed to each */ +/* emitter during the decomposition. It can be */ +/* used to store the state during the */ +/* decomposition. */ +/* */ +/* */ +/* Error code. 0 means success. */ +/* */ +static int SW_FT_Outline_Decompose(const SW_FT_Outline* outline, + const SW_FT_Outline_Funcs* func_interface, + void* user) +{ #undef SCALED -#define SCALED( x ) ( ( (x) << shift ) - delta ) +#define SCALED(x) (((x) << shift) - delta) - SW_FT_Vector v_last; - SW_FT_Vector v_control; - SW_FT_Vector v_start; + SW_FT_Vector v_last; + SW_FT_Vector v_control; + SW_FT_Vector v_start; - SW_FT_Vector* point; - SW_FT_Vector* limit; - char* tags; + SW_FT_Vector* point; + SW_FT_Vector* limit; + char* tags; - int error; + int error; - int n; /* index of contour in outline */ - int first; /* index of first point in contour */ - char tag; /* current point's state */ + int n; /* index of contour in outline */ + int first; /* index of first point in contour */ + char tag; /* current point's state */ - int shift; - TPos delta; + int shift; + TPos delta; - - if ( !outline || !func_interface ) - return SW_FT_THROW( Invalid_Argument ); + if (!outline || !func_interface) return SW_FT_THROW(Invalid_Argument); shift = func_interface->shift; delta = func_interface->delta; first = 0; - for ( n = 0; n < outline->n_contours; n++ ) - { - int last; /* index of last point in contour */ - - - last = outline->contours[n]; - if ( last < 0 ) - goto Invalid_Outline; - limit = outline->points + last; - - v_start = outline->points[first]; - v_start.x = SCALED( v_start.x ); - v_start.y = SCALED( v_start.y ); - - v_last = outline->points[last]; - v_last.x = SCALED( v_last.x ); - v_last.y = SCALED( v_last.y ); - - v_control = v_start; - - point = outline->points + first; - tags = outline->tags + first; - tag = SW_FT_CURVE_TAG( tags[0] ); - - /* A contour cannot start with a cubic control point! */ - if ( tag == SW_FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; - - /* check first point to determine origin */ - if ( tag == SW_FT_CURVE_TAG_CONIC ) - { - /* first point is conic control. Yes, this happens. */ - if ( SW_FT_CURVE_TAG( outline->tags[last] ) == SW_FT_CURVE_TAG_ON ) - { - /* start at last point if it is on the curve */ - v_start = v_last; - limit--; - } - else - { - /* if both first and last points are conic, */ - /* start at their middle and record its position */ - /* for closure */ - v_start.x = ( v_start.x + v_last.x ) / 2; - v_start.y = ( v_start.y + v_last.y ) / 2; + for (n = 0; n < outline->n_contours; n++) { + int last; /* index of last point in contour */ + + last = outline->contours[n]; + if (last < 0) goto Invalid_Outline; + limit = outline->points + last; + + v_start = outline->points[first]; + v_start.x = SCALED(v_start.x); + v_start.y = SCALED(v_start.y); + + v_last = outline->points[last]; + v_last.x = SCALED(v_last.x); + v_last.y = SCALED(v_last.y); + + v_control = v_start; + + point = outline->points + first; + tags = outline->tags + first; + tag = SW_FT_CURVE_TAG(tags[0]); + + /* A contour cannot start with a cubic control point! */ + if (tag == SW_FT_CURVE_TAG_CUBIC) goto Invalid_Outline; + + /* check first point to determine origin */ + if (tag == SW_FT_CURVE_TAG_CONIC) { + /* first point is conic control. Yes, this happens. */ + if (SW_FT_CURVE_TAG(outline->tags[last]) == SW_FT_CURVE_TAG_ON) { + /* start at last point if it is on the curve */ + v_start = v_last; + limit--; + } else { + /* if both first and last points are conic, */ + /* start at their middle and record its position */ + /* for closure */ + v_start.x = (v_start.x + v_last.x) / 2; + v_start.y = (v_start.y + v_last.y) / 2; + } + point--; + tags--; } - point--; - tags--; - } - - error = func_interface->move_to( &v_start, user ); - if ( error ) - goto Exit; - while ( point < limit ) - { - point++; - tags++; + error = func_interface->move_to(&v_start, user); + if (error) goto Exit; - tag = SW_FT_CURVE_TAG( tags[0] ); - switch ( tag ) - { - case SW_FT_CURVE_TAG_ON: /* emit a single line_to */ - { - SW_FT_Vector vec; - - - vec.x = SCALED( point->x ); - vec.y = SCALED( point->y ); + while (point < limit) { + point++; + tags++; - error = func_interface->line_to( &vec, user ); - if ( error ) - goto Exit; - continue; - } + tag = SW_FT_CURVE_TAG(tags[0]); + switch (tag) { + case SW_FT_CURVE_TAG_ON: /* emit a single line_to */ + { + SW_FT_Vector vec; - case SW_FT_CURVE_TAG_CONIC: /* consume conic arcs */ - v_control.x = SCALED( point->x ); - v_control.y = SCALED( point->y ); + vec.x = SCALED(point->x); + vec.y = SCALED(point->y); - Do_Conic: - if ( point < limit ) - { - SW_FT_Vector vec; - SW_FT_Vector v_middle; + error = func_interface->line_to(&vec, user); + if (error) goto Exit; + continue; + } + case SW_FT_CURVE_TAG_CONIC: /* consume conic arcs */ + v_control.x = SCALED(point->x); + v_control.y = SCALED(point->y); - point++; - tags++; - tag = SW_FT_CURVE_TAG( tags[0] ); + Do_Conic: + if (point < limit) { + SW_FT_Vector vec; + SW_FT_Vector v_middle; - vec.x = SCALED( point->x ); - vec.y = SCALED( point->y ); + point++; + tags++; + tag = SW_FT_CURVE_TAG(tags[0]); - if ( tag == SW_FT_CURVE_TAG_ON ) - { - error = func_interface->conic_to( &v_control, &vec, user ); - if ( error ) - goto Exit; - continue; - } + vec.x = SCALED(point->x); + vec.y = SCALED(point->y); - if ( tag != SW_FT_CURVE_TAG_CONIC ) - goto Invalid_Outline; + if (tag == SW_FT_CURVE_TAG_ON) { + error = + func_interface->conic_to(&v_control, &vec, user); + if (error) goto Exit; + continue; + } - v_middle.x = ( v_control.x + vec.x ) / 2; - v_middle.y = ( v_control.y + vec.y ) / 2; + if (tag != SW_FT_CURVE_TAG_CONIC) goto Invalid_Outline; - error = func_interface->conic_to( &v_control, &v_middle, user ); - if ( error ) - goto Exit; + v_middle.x = (v_control.x + vec.x) / 2; + v_middle.y = (v_control.y + vec.y) / 2; - v_control = vec; - goto Do_Conic; - } + error = + func_interface->conic_to(&v_control, &v_middle, user); + if (error) goto Exit; - error = func_interface->conic_to( &v_control, &v_start, user ); - goto Close; + v_control = vec; + goto Do_Conic; + } - default: /* SW_FT_CURVE_TAG_CUBIC */ - { - SW_FT_Vector vec1, vec2; + error = func_interface->conic_to(&v_control, &v_start, user); + goto Close; + default: /* SW_FT_CURVE_TAG_CUBIC */ + { + SW_FT_Vector vec1, vec2; - if ( point + 1 > limit || - SW_FT_CURVE_TAG( tags[1] ) != SW_FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; + if (point + 1 > limit || + SW_FT_CURVE_TAG(tags[1]) != SW_FT_CURVE_TAG_CUBIC) + goto Invalid_Outline; - point += 2; - tags += 2; + point += 2; + tags += 2; - vec1.x = SCALED( point[-2].x ); - vec1.y = SCALED( point[-2].y ); + vec1.x = SCALED(point[-2].x); + vec1.y = SCALED(point[-2].y); - vec2.x = SCALED( point[-1].x ); - vec2.y = SCALED( point[-1].y ); + vec2.x = SCALED(point[-1].x); + vec2.y = SCALED(point[-1].y); - if ( point <= limit ) - { - SW_FT_Vector vec; + if (point <= limit) { + SW_FT_Vector vec; + vec.x = SCALED(point->x); + vec.y = SCALED(point->y); - vec.x = SCALED( point->x ); - vec.y = SCALED( point->y ); + error = func_interface->cubic_to(&vec1, &vec2, &vec, user); + if (error) goto Exit; + continue; + } - error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); - if ( error ) - goto Exit; - continue; + error = func_interface->cubic_to(&vec1, &vec2, &v_start, user); + goto Close; + } } - - error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); - goto Close; - } } - } - /* close the contour with a line segment */ - error = func_interface->line_to( &v_start, user ); + /* close the contour with a line segment */ + error = func_interface->line_to(&v_start, user); - Close: - if ( error ) - goto Exit; + Close: + if (error) goto Exit; - first = last + 1; + first = last + 1; } return 0; - Exit: +Exit: return error; - Invalid_Outline: - return SW_FT_THROW( Invalid_Outline ); - } - - - typedef struct gray_TBand_ - { - TPos min, max; +Invalid_Outline: + return SW_FT_THROW(Invalid_Outline); +} - } gray_TBand; +typedef struct gray_TBand_ { + TPos min, max; +} gray_TBand; +SW_FT_DEFINE_OUTLINE_FUNCS(func_interface, + (SW_FT_Outline_MoveTo_Func)gray_move_to, + (SW_FT_Outline_LineTo_Func)gray_line_to, + (SW_FT_Outline_ConicTo_Func)gray_conic_to, + (SW_FT_Outline_CubicTo_Func)gray_cubic_to, 0, 0) - SW_FT_DEFINE_OUTLINE_FUNCS(func_interface, - (SW_FT_Outline_MoveTo_Func) gray_move_to, - (SW_FT_Outline_LineTo_Func) gray_line_to, - (SW_FT_Outline_ConicTo_Func)gray_conic_to, - (SW_FT_Outline_CubicTo_Func)gray_cubic_to, - 0, - 0 - ) - - static int - gray_convert_glyph_inner( RAS_ARG ) - { +static int gray_convert_glyph_inner(RAS_ARG) +{ + volatile int error = 0; - volatile int error = 0; - - if ( ft_setjmp( ras.jump_buffer ) == 0 ) - { - error = SW_FT_Outline_Decompose( &ras.outline, &func_interface, &ras ); - if ( !ras.invalid ) - gray_record_cell( RAS_VAR ); - } - else - error = SW_FT_THROW( Memory_Overflow ); + if (ft_setjmp(ras.jump_buffer) == 0) { + error = SW_FT_Outline_Decompose(&ras.outline, &func_interface, &ras); + if (!ras.invalid) gray_record_cell(RAS_VAR); + } else + error = SW_FT_THROW(Memory_Overflow); return error; - } - - - static int - gray_convert_glyph( RAS_ARG ) - { - gray_TBand bands[40]; - gray_TBand* volatile band; - int volatile n, num_bands; - TPos volatile min, max, max_y; - SW_FT_BBox* clip; +} +static int gray_convert_glyph(RAS_ARG) +{ + gray_TBand bands[40]; + gray_TBand* volatile band; + int volatile n, num_bands; + TPos volatile min, max, max_y; + SW_FT_BBox* clip; /* Set up state in the raster object */ - gray_compute_cbox( RAS_VAR ); + gray_compute_cbox(RAS_VAR); /* clip to target bitmap, exit if nothing to do */ clip = &ras.clip_box; - if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax || - ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax ) - return 0; + if (ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax || + ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax) + return 0; - if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin; - if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin; + if (ras.min_ex < clip->xMin) ras.min_ex = clip->xMin; + if (ras.min_ey < clip->yMin) ras.min_ey = clip->yMin; - if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax; - if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax; + if (ras.max_ex > clip->xMax) ras.max_ex = clip->xMax; + if (ras.max_ey > clip->yMax) ras.max_ey = clip->yMax; ras.count_ex = ras.max_ex - ras.min_ex; ras.count_ey = ras.max_ey - ras.min_ey; /* set up vertical bands */ - num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size ); - if ( num_bands == 0 ) - num_bands = 1; - if ( num_bands >= 39 ) - num_bands = 39; + num_bands = (int)((ras.max_ey - ras.min_ey) / ras.band_size); + if (num_bands == 0) num_bands = 1; + if (num_bands >= 39) num_bands = 39; ras.band_shoot = 0; - min = ras.min_ey; + min = ras.min_ey; max_y = ras.max_ey; - for ( n = 0; n < num_bands; n++, min = max ) - { - max = min + ras.band_size; - if ( n == num_bands - 1 || max > max_y ) - max = max_y; - - bands[0].min = min; - bands[0].max = max; - band = bands; + for (n = 0; n < num_bands; n++, min = max) { + max = min + ras.band_size; + if (n == num_bands - 1 || max > max_y) max = max_y; - while ( band >= bands ) - { - TPos bottom, top, middle; - int error; + bands[0].min = min; + bands[0].max = max; + band = bands; - { - PCell cells_max; - int yindex; - long cell_start, cell_end, cell_mod; + while (band >= bands) { + TPos bottom, top, middle; + int error; + { + PCell cells_max; + int yindex; + long cell_start, cell_end, cell_mod; - ras.ycells = (PCell*)ras.buffer; - ras.ycount = band->max - band->min; + ras.ycells = (PCell*)ras.buffer; + ras.ycount = band->max - band->min; - cell_start = sizeof ( PCell ) * ras.ycount; - cell_mod = cell_start % sizeof ( TCell ); - if ( cell_mod > 0 ) - cell_start += sizeof ( TCell ) - cell_mod; + cell_start = sizeof(PCell) * ras.ycount; + cell_mod = cell_start % sizeof(TCell); + if (cell_mod > 0) cell_start += sizeof(TCell) - cell_mod; - cell_end = ras.buffer_size; - cell_end -= cell_end % sizeof ( TCell ); + cell_end = ras.buffer_size; + cell_end -= cell_end % sizeof(TCell); - cells_max = (PCell)( (char*)ras.buffer + cell_end ); - ras.cells = (PCell)( (char*)ras.buffer + cell_start ); - if ( ras.cells >= cells_max ) - goto ReduceBands; + cells_max = (PCell)((char*)ras.buffer + cell_end); + ras.cells = (PCell)((char*)ras.buffer + cell_start); + if (ras.cells >= cells_max) goto ReduceBands; - ras.max_cells = cells_max - ras.cells; - if ( ras.max_cells < 2 ) - goto ReduceBands; + ras.max_cells = cells_max - ras.cells; + if (ras.max_cells < 2) goto ReduceBands; - for ( yindex = 0; yindex < ras.ycount; yindex++ ) - ras.ycells[yindex] = NULL; - } + for (yindex = 0; yindex < ras.ycount; yindex++) + ras.ycells[yindex] = NULL; + } - ras.num_cells = 0; - ras.invalid = 1; - ras.min_ey = band->min; - ras.max_ey = band->max; - ras.count_ey = band->max - band->min; + ras.num_cells = 0; + ras.invalid = 1; + ras.min_ey = band->min; + ras.max_ey = band->max; + ras.count_ey = band->max - band->min; + + error = gray_convert_glyph_inner(RAS_VAR); + + if (!error) { + gray_sweep(RAS_VAR); + band--; + continue; + } else if (error != ErrRaster_Memory_Overflow) + return 1; + + ReduceBands: + /* render pool overflow; we will reduce the render band by half */ + bottom = band->min; + top = band->max; + middle = bottom + ((top - bottom) >> 1); + + /* This is too complex for a single scanline; there must */ + /* be some problems. */ + if (middle == bottom) { + return 1; + } - error = gray_convert_glyph_inner( RAS_VAR ); + if (bottom - top >= ras.band_size) ras.band_shoot++; - if ( !error ) - { - gray_sweep( RAS_VAR); - band--; - continue; + band[1].min = bottom; + band[1].max = middle; + band[0].min = middle; + band[0].max = top; + band++; } - else if ( error != ErrRaster_Memory_Overflow ) - return 1; - - ReduceBands: - /* render pool overflow; we will reduce the render band by half */ - bottom = band->min; - top = band->max; - middle = bottom + ( ( top - bottom ) >> 1 ); - - /* This is too complex for a single scanline; there must */ - /* be some problems. */ - if ( middle == bottom ) - { - return 1; - } - - if ( bottom-top >= ras.band_size ) - ras.band_shoot++; - - band[1].min = bottom; - band[1].max = middle; - band[0].min = middle; - band[0].max = top; - band++; - } } - if ( ras.band_shoot > 8 && ras.band_size > 16 ) - ras.band_size = ras.band_size / 2; + if (ras.band_shoot > 8 && ras.band_size > 16) + ras.band_size = ras.band_size / 2; return 0; - } - - static int - gray_raster_render( gray_PRaster raster, - const SW_FT_Raster_Params* params ) - { - SW_FT_UNUSED( raster ); - const SW_FT_Outline* outline = (const SW_FT_Outline*)params->source; +} - gray_TWorker worker[1]; +static int gray_raster_render(gray_PRaster raster, + const SW_FT_Raster_Params* params) +{ + SW_FT_UNUSED(raster); + const SW_FT_Outline* outline = (const SW_FT_Outline*)params->source; - TCell buffer[SW_FT_RENDER_POOL_SIZE / sizeof ( TCell )]; - long buffer_size = sizeof ( buffer ); - int band_size = (int)( buffer_size / - (long)( sizeof ( TCell ) * 8 ) ); + gray_TWorker worker[1]; + TCell buffer[SW_FT_RENDER_POOL_SIZE / sizeof(TCell)]; + long buffer_size = sizeof(buffer); + int band_size = (int)(buffer_size / (long)(sizeof(TCell) * 8)); - if ( !outline ) - return SW_FT_THROW( Invalid_Outline ); + if (!outline) return SW_FT_THROW(Invalid_Outline); /* return immediately if the outline is empty */ - if ( outline->n_points == 0 || outline->n_contours <= 0 ) - return 0; + if (outline->n_points == 0 || outline->n_contours <= 0) return 0; - if ( !outline->contours || !outline->points ) - return SW_FT_THROW( Invalid_Outline ); + if (!outline->contours || !outline->points) + return SW_FT_THROW(Invalid_Outline); - if ( outline->n_points != - outline->contours[outline->n_contours - 1] + 1 ) - return SW_FT_THROW( Invalid_Outline ); + if (outline->n_points != outline->contours[outline->n_contours - 1] + 1) + return SW_FT_THROW(Invalid_Outline); /* this version does not support monochrome rendering */ - if ( !( params->flags & SW_FT_RASTER_FLAG_AA ) ) - return SW_FT_THROW( Invalid_Mode ); - - if ( params->flags & SW_FT_RASTER_FLAG_CLIP ) - ras.clip_box = params->clip_box; - else - { - ras.clip_box.xMin = -32768L; - ras.clip_box.yMin = -32768L; - ras.clip_box.xMax = 32767L; - ras.clip_box.yMax = 32767L; + if (!(params->flags & SW_FT_RASTER_FLAG_AA)) + return SW_FT_THROW(Invalid_Mode); + + if (params->flags & SW_FT_RASTER_FLAG_CLIP) + ras.clip_box = params->clip_box; + else { + ras.clip_box.xMin = -32768L; + ras.clip_box.yMin = -32768L; + ras.clip_box.xMax = 32767L; + ras.clip_box.yMax = 32767L; } - gray_init_cells( RAS_VAR_ buffer, buffer_size ); + gray_init_cells(RAS_VAR_ buffer, buffer_size); - ras.outline = *outline; - ras.num_cells = 0; - ras.invalid = 1; - ras.band_size = band_size; + ras.outline = *outline; + ras.num_cells = 0; + ras.invalid = 1; + ras.band_size = band_size; ras.num_gray_spans = 0; - ras.render_span = (SW_FT_Raster_Span_Func)params->gray_spans; + ras.render_span = (SW_FT_Raster_Span_Func)params->gray_spans; ras.render_span_data = params->user; - return gray_convert_glyph( RAS_VAR ); - } + return gray_convert_glyph(RAS_VAR); +} - /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/ - /**** a static object. *****/ +/**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/ +/**** a static object. *****/ - static int - gray_raster_new(SW_FT_Raster* araster ) - { - static gray_TRaster the_raster; +static int gray_raster_new(SW_FT_Raster* araster) +{ + static gray_TRaster the_raster; *araster = (SW_FT_Raster)&the_raster; - SW_FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) ); + SW_FT_MEM_ZERO(&the_raster, sizeof(the_raster)); return 0; - } +} - - static void - gray_raster_done( SW_FT_Raster raster ) - { +static void gray_raster_done(SW_FT_Raster raster) +{ /* nothing */ - SW_FT_UNUSED( raster ); - } - - static void - gray_raster_reset( SW_FT_Raster raster, - char* pool_base, - long pool_size ) - { - SW_FT_UNUSED( raster ); - SW_FT_UNUSED( pool_base ); - SW_FT_UNUSED( pool_size ); - } + SW_FT_UNUSED(raster); +} +static void gray_raster_reset(SW_FT_Raster raster, char* pool_base, + long pool_size) +{ + SW_FT_UNUSED(raster); + SW_FT_UNUSED(pool_base); + SW_FT_UNUSED(pool_size); +} - SW_FT_DEFINE_RASTER_FUNCS(sw_ft_grays_raster, - - (SW_FT_Raster_New_Func) gray_raster_new, - (SW_FT_Raster_Reset_Func) gray_raster_reset, - (SW_FT_Raster_Render_Func) gray_raster_render, - (SW_FT_Raster_Done_Func) gray_raster_done - ) +SW_FT_DEFINE_RASTER_FUNCS(sw_ft_grays_raster, + (SW_FT_Raster_New_Func)gray_raster_new, + (SW_FT_Raster_Reset_Func)gray_raster_reset, + (SW_FT_Raster_Render_Func)gray_raster_render, + (SW_FT_Raster_Done_Func)gray_raster_done) /* END */ diff --git a/src/vector/freetype/v_ft_stroker.cpp b/src/vector/freetype/v_ft_stroker.cpp index 3315262..7192d53 100644 --- a/src/vector/freetype/v_ft_stroker.cpp +++ b/src/vector/freetype/v_ft_stroker.cpp @@ -16,157 +16,128 @@ /* */ /***************************************************************************/ - -#include "v_ft_math.h" #include "v_ft_stroker.h" #include -#include #include +#include +#include "v_ft_math.h" +/*************************************************************************/ +/*************************************************************************/ +/***** *****/ +/***** BEZIER COMPUTATIONS *****/ +/***** *****/ +/*************************************************************************/ +/*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** BEZIER COMPUTATIONS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - -#define SW_FT_SMALL_CONIC_THRESHOLD ( SW_FT_ANGLE_PI / 6 ) -#define SW_FT_SMALL_CUBIC_THRESHOLD ( SW_FT_ANGLE_PI / 8 ) - -#define SW_FT_EPSILON 2 +#define SW_FT_SMALL_CONIC_THRESHOLD (SW_FT_ANGLE_PI / 6) +#define SW_FT_SMALL_CUBIC_THRESHOLD (SW_FT_ANGLE_PI / 8) -#define SW_FT_IS_SMALL( x ) ( (x) > -SW_FT_EPSILON && (x) < SW_FT_EPSILON ) +#define SW_FT_EPSILON 2 +#define SW_FT_IS_SMALL(x) ((x) > -SW_FT_EPSILON && (x) < SW_FT_EPSILON) - static SW_FT_Pos - ft_pos_abs( SW_FT_Pos x ) - { +static SW_FT_Pos ft_pos_abs(SW_FT_Pos x) +{ return x >= 0 ? x : -x; - } - - - static void - ft_conic_split( SW_FT_Vector* base ) - { - SW_FT_Pos a, b; +} +static void ft_conic_split(SW_FT_Vector* base) +{ + SW_FT_Pos a, b; base[4].x = base[2].x; b = base[1].x; - a = base[3].x = ( base[2].x + b ) / 2; - b = base[1].x = ( base[0].x + b ) / 2; - base[2].x = ( a + b ) / 2; + a = base[3].x = (base[2].x + b) / 2; + b = base[1].x = (base[0].x + b) / 2; + base[2].x = (a + b) / 2; base[4].y = base[2].y; b = base[1].y; - a = base[3].y = ( base[2].y + b ) / 2; - b = base[1].y = ( base[0].y + b ) / 2; - base[2].y = ( a + b ) / 2; - } - - - static SW_FT_Bool - ft_conic_is_small_enough( SW_FT_Vector* base, - SW_FT_Angle *angle_in, - SW_FT_Angle *angle_out ) - { - SW_FT_Vector d1, d2; - SW_FT_Angle theta; - SW_FT_Int close1, close2; - + a = base[3].y = (base[2].y + b) / 2; + b = base[1].y = (base[0].y + b) / 2; + base[2].y = (a + b) / 2; +} + +static SW_FT_Bool ft_conic_is_small_enough(SW_FT_Vector* base, + SW_FT_Angle* angle_in, + SW_FT_Angle* angle_out) +{ + SW_FT_Vector d1, d2; + SW_FT_Angle theta; + SW_FT_Int close1, close2; d1.x = base[1].x - base[2].x; d1.y = base[1].y - base[2].y; d2.x = base[0].x - base[1].x; d2.y = base[0].y - base[1].y; - close1 = SW_FT_IS_SMALL( d1.x ) && SW_FT_IS_SMALL( d1.y ); - close2 = SW_FT_IS_SMALL( d2.x ) && SW_FT_IS_SMALL( d2.y ); + close1 = SW_FT_IS_SMALL(d1.x) && SW_FT_IS_SMALL(d1.y); + close2 = SW_FT_IS_SMALL(d2.x) && SW_FT_IS_SMALL(d2.y); - if ( close1 ) - { - if ( close2 ) - { - /* basically a point; */ - /* do nothing to retain original direction */ - } - else - { - *angle_in = - *angle_out = SW_FT_Atan2( d2.x, d2.y ); - } - } - else /* !close1 */ + if (close1) { + if (close2) { + /* basically a point; */ + /* do nothing to retain original direction */ + } else { + *angle_in = *angle_out = SW_FT_Atan2(d2.x, d2.y); + } + } else /* !close1 */ { - if ( close2 ) - { - *angle_in = - *angle_out = SW_FT_Atan2( d1.x, d1.y ); - } - else - { - *angle_in = SW_FT_Atan2( d1.x, d1.y ); - *angle_out = SW_FT_Atan2( d2.x, d2.y ); - } + if (close2) { + *angle_in = *angle_out = SW_FT_Atan2(d1.x, d1.y); + } else { + *angle_in = SW_FT_Atan2(d1.x, d1.y); + *angle_out = SW_FT_Atan2(d2.x, d2.y); + } } - theta = ft_pos_abs( SW_FT_Angle_Diff( *angle_in, *angle_out ) ); - - return SW_FT_BOOL( theta < SW_FT_SMALL_CONIC_THRESHOLD ); - } - + theta = ft_pos_abs(SW_FT_Angle_Diff(*angle_in, *angle_out)); - static void - ft_cubic_split( SW_FT_Vector* base ) - { - SW_FT_Pos a, b, c, d; + return SW_FT_BOOL(theta < SW_FT_SMALL_CONIC_THRESHOLD); +} +static void ft_cubic_split(SW_FT_Vector* base) +{ + SW_FT_Pos a, b, c, d; base[6].x = base[3].x; c = base[1].x; d = base[2].x; - base[1].x = a = ( base[0].x + c ) / 2; - base[5].x = b = ( base[3].x + d ) / 2; - c = ( c + d ) / 2; - base[2].x = a = ( a + c ) / 2; - base[4].x = b = ( b + c ) / 2; - base[3].x = ( a + b ) / 2; + base[1].x = a = (base[0].x + c) / 2; + base[5].x = b = (base[3].x + d) / 2; + c = (c + d) / 2; + base[2].x = a = (a + c) / 2; + base[4].x = b = (b + c) / 2; + base[3].x = (a + b) / 2; base[6].y = base[3].y; c = base[1].y; d = base[2].y; - base[1].y = a = ( base[0].y + c ) / 2; - base[5].y = b = ( base[3].y + d ) / 2; - c = ( c + d ) / 2; - base[2].y = a = ( a + c ) / 2; - base[4].y = b = ( b + c ) / 2; - base[3].y = ( a + b ) / 2; - } - - - /* Return the average of `angle1' and `angle2'. */ - /* This gives correct result even if `angle1' and `angle2' */ - /* have opposite signs. */ - static SW_FT_Angle - ft_angle_mean( SW_FT_Angle angle1, - SW_FT_Angle angle2 ) - { - return angle1 + SW_FT_Angle_Diff( angle1, angle2 ) / 2; - } - - - static SW_FT_Bool - ft_cubic_is_small_enough( SW_FT_Vector* base, - SW_FT_Angle *angle_in, - SW_FT_Angle *angle_mid, - SW_FT_Angle *angle_out ) - { - SW_FT_Vector d1, d2, d3; - SW_FT_Angle theta1, theta2; - SW_FT_Int close1, close2, close3; - + base[1].y = a = (base[0].y + c) / 2; + base[5].y = b = (base[3].y + d) / 2; + c = (c + d) / 2; + base[2].y = a = (a + c) / 2; + base[4].y = b = (b + c) / 2; + base[3].y = (a + b) / 2; +} + +/* Return the average of `angle1' and `angle2'. */ +/* This gives correct result even if `angle1' and `angle2' */ +/* have opposite signs. */ +static SW_FT_Angle ft_angle_mean(SW_FT_Angle angle1, SW_FT_Angle angle2) +{ + return angle1 + SW_FT_Angle_Diff(angle1, angle2) / 2; +} + +static SW_FT_Bool ft_cubic_is_small_enough(SW_FT_Vector* base, + SW_FT_Angle* angle_in, + SW_FT_Angle* angle_mid, + SW_FT_Angle* angle_out) +{ + SW_FT_Vector d1, d2, d3; + SW_FT_Angle theta1, theta2; + SW_FT_Int close1, close2, close3; d1.x = base[2].x - base[3].x; d1.y = base[2].y - base[3].y; @@ -175,1642 +146,1376 @@ d3.x = base[0].x - base[1].x; d3.y = base[0].y - base[1].y; - close1 = SW_FT_IS_SMALL( d1.x ) && SW_FT_IS_SMALL( d1.y ); - close2 = SW_FT_IS_SMALL( d2.x ) && SW_FT_IS_SMALL( d2.y ); - close3 = SW_FT_IS_SMALL( d3.x ) && SW_FT_IS_SMALL( d3.y ); + close1 = SW_FT_IS_SMALL(d1.x) && SW_FT_IS_SMALL(d1.y); + close2 = SW_FT_IS_SMALL(d2.x) && SW_FT_IS_SMALL(d2.y); + close3 = SW_FT_IS_SMALL(d3.x) && SW_FT_IS_SMALL(d3.y); - if ( close1 ) - { - if ( close2 ) - { - if ( close3 ) - { - /* basically a point; */ - /* do nothing to retain original direction */ - } - else /* !close3 */ - { - *angle_in = - *angle_mid = - *angle_out = SW_FT_Atan2( d3.x, d3.y ); - } - } - else /* !close2 */ - { - if ( close3 ) - { - *angle_in = - *angle_mid = - *angle_out = SW_FT_Atan2( d2.x, d2.y ); - } - else /* !close3 */ + if (close1) { + if (close2) { + if (close3) { + /* basically a point; */ + /* do nothing to retain original direction */ + } else /* !close3 */ + { + *angle_in = *angle_mid = *angle_out = SW_FT_Atan2(d3.x, d3.y); + } + } else /* !close2 */ { - *angle_in = - *angle_mid = SW_FT_Atan2( d2.x, d2.y ); - *angle_out = SW_FT_Atan2( d3.x, d3.y ); + if (close3) { + *angle_in = *angle_mid = *angle_out = SW_FT_Atan2(d2.x, d2.y); + } else /* !close3 */ + { + *angle_in = *angle_mid = SW_FT_Atan2(d2.x, d2.y); + *angle_out = SW_FT_Atan2(d3.x, d3.y); + } } - } - } - else /* !close1 */ + } else /* !close1 */ { - if ( close2 ) - { - if ( close3 ) - { - *angle_in = - *angle_mid = - *angle_out = SW_FT_Atan2( d1.x, d1.y ); - } - else /* !close3 */ - { - *angle_in = SW_FT_Atan2( d1.x, d1.y ); - *angle_out = SW_FT_Atan2( d3.x, d3.y ); - *angle_mid = ft_angle_mean( *angle_in, *angle_out ); - } - } - else /* !close2 */ - { - if ( close3 ) - { - *angle_in = SW_FT_Atan2( d1.x, d1.y ); - *angle_mid = - *angle_out = SW_FT_Atan2( d2.x, d2.y ); - } - else /* !close3 */ + if (close2) { + if (close3) { + *angle_in = *angle_mid = *angle_out = SW_FT_Atan2(d1.x, d1.y); + } else /* !close3 */ + { + *angle_in = SW_FT_Atan2(d1.x, d1.y); + *angle_out = SW_FT_Atan2(d3.x, d3.y); + *angle_mid = ft_angle_mean(*angle_in, *angle_out); + } + } else /* !close2 */ { - *angle_in = SW_FT_Atan2( d1.x, d1.y ); - *angle_mid = SW_FT_Atan2( d2.x, d2.y ); - *angle_out = SW_FT_Atan2( d3.x, d3.y ); + if (close3) { + *angle_in = SW_FT_Atan2(d1.x, d1.y); + *angle_mid = *angle_out = SW_FT_Atan2(d2.x, d2.y); + } else /* !close3 */ + { + *angle_in = SW_FT_Atan2(d1.x, d1.y); + *angle_mid = SW_FT_Atan2(d2.x, d2.y); + *angle_out = SW_FT_Atan2(d3.x, d3.y); + } } - } } - theta1 = ft_pos_abs( SW_FT_Angle_Diff( *angle_in, *angle_mid ) ); - theta2 = ft_pos_abs( SW_FT_Angle_Diff( *angle_mid, *angle_out ) ); - - return SW_FT_BOOL( theta1 < SW_FT_SMALL_CUBIC_THRESHOLD && - theta2 < SW_FT_SMALL_CUBIC_THRESHOLD ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** STROKE BORDERS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - typedef enum SW_FT_StrokeTags_ - { - SW_FT_STROKE_TAG_ON = 1, /* on-curve point */ - SW_FT_STROKE_TAG_CUBIC = 2, /* cubic off-point */ - SW_FT_STROKE_TAG_BEGIN = 4, /* sub-path start */ - SW_FT_STROKE_TAG_END = 8 /* sub-path end */ - - } SW_FT_StrokeTags; - -#define SW_FT_STROKE_TAG_BEGIN_END ( SW_FT_STROKE_TAG_BEGIN | SW_FT_STROKE_TAG_END ) - - typedef struct SW_FT_StrokeBorderRec_ - { - SW_FT_UInt num_points; - SW_FT_UInt max_points; - SW_FT_Vector* points; - SW_FT_Byte* tags; - SW_FT_Bool movable; /* TRUE for ends of lineto borders */ - SW_FT_Int start; /* index of current sub-path start point */ - SW_FT_Bool valid; - - } SW_FT_StrokeBorderRec, *SW_FT_StrokeBorder; - - - - SW_FT_Error - SW_FT_Outline_Check( SW_FT_Outline* outline ) - { - if ( outline ) - { - SW_FT_Int n_points = outline->n_points; - SW_FT_Int n_contours = outline->n_contours; - SW_FT_Int end0, end; - SW_FT_Int n; + theta1 = ft_pos_abs(SW_FT_Angle_Diff(*angle_in, *angle_mid)); + theta2 = ft_pos_abs(SW_FT_Angle_Diff(*angle_mid, *angle_out)); + + return SW_FT_BOOL(theta1 < SW_FT_SMALL_CUBIC_THRESHOLD && + theta2 < SW_FT_SMALL_CUBIC_THRESHOLD); +} + +/*************************************************************************/ +/*************************************************************************/ +/***** *****/ +/***** STROKE BORDERS *****/ +/***** *****/ +/*************************************************************************/ +/*************************************************************************/ + +typedef enum SW_FT_StrokeTags_ { + SW_FT_STROKE_TAG_ON = 1, /* on-curve point */ + SW_FT_STROKE_TAG_CUBIC = 2, /* cubic off-point */ + SW_FT_STROKE_TAG_BEGIN = 4, /* sub-path start */ + SW_FT_STROKE_TAG_END = 8 /* sub-path end */ + +} SW_FT_StrokeTags; + +#define SW_FT_STROKE_TAG_BEGIN_END \ + (SW_FT_STROKE_TAG_BEGIN | SW_FT_STROKE_TAG_END) + +typedef struct SW_FT_StrokeBorderRec_ { + SW_FT_UInt num_points; + SW_FT_UInt max_points; + SW_FT_Vector* points; + SW_FT_Byte* tags; + SW_FT_Bool movable; /* TRUE for ends of lineto borders */ + SW_FT_Int start; /* index of current sub-path start point */ + SW_FT_Bool valid; + +} SW_FT_StrokeBorderRec, *SW_FT_StrokeBorder; + +SW_FT_Error SW_FT_Outline_Check(SW_FT_Outline* outline) +{ + if (outline) { + SW_FT_Int n_points = outline->n_points; + SW_FT_Int n_contours = outline->n_contours; + SW_FT_Int end0, end; + SW_FT_Int n; + + /* empty glyph? */ + if (n_points == 0 && n_contours == 0) return 0; + + /* check point and contour counts */ + if (n_points <= 0 || n_contours <= 0) goto Bad; + + end0 = end = -1; + for (n = 0; n < n_contours; n++) { + end = outline->contours[n]; + + /* note that we don't accept empty contours */ + if (end <= end0 || end >= n_points) goto Bad; + + end0 = end; + } + if (end != n_points - 1) goto Bad; - /* empty glyph? */ - if ( n_points == 0 && n_contours == 0 ) + /* XXX: check the tags array */ return 0; - - /* check point and contour counts */ - if ( n_points <= 0 || n_contours <= 0 ) - goto Bad; - - end0 = end = -1; - for ( n = 0; n < n_contours; n++ ) - { - end = outline->contours[n]; - - /* note that we don't accept empty contours */ - if ( end <= end0 || end >= n_points ) - goto Bad; - - end0 = end; - } - - if ( end != n_points - 1 ) - goto Bad; - - /* XXX: check the tags array */ - return 0; } - Bad: - return -1;//SW_FT_THROW( Invalid_Argument ); - } - - - - void - SW_FT_Outline_Get_CBox( const SW_FT_Outline* outline, - SW_FT_BBox *acbox ) - { - SW_FT_Pos xMin, yMin, xMax, yMax; - - - if ( outline && acbox ) - { - if ( outline->n_points == 0 ) - { - xMin = 0; - yMin = 0; - xMax = 0; - yMax = 0; - } - else - { - SW_FT_Vector* vec = outline->points; - SW_FT_Vector* limit = vec + outline->n_points; - - - xMin = xMax = vec->x; - yMin = yMax = vec->y; - vec++; - - for ( ; vec < limit; vec++ ) - { - SW_FT_Pos x, y; - - - x = vec->x; - if ( x < xMin ) xMin = x; - if ( x > xMax ) xMax = x; - - y = vec->y; - if ( y < yMin ) yMin = y; - if ( y > yMax ) yMax = y; +Bad: + return -1; // SW_FT_THROW( Invalid_Argument ); +} + +void SW_FT_Outline_Get_CBox(const SW_FT_Outline* outline, SW_FT_BBox* acbox) +{ + SW_FT_Pos xMin, yMin, xMax, yMax; + + if (outline && acbox) { + if (outline->n_points == 0) { + xMin = 0; + yMin = 0; + xMax = 0; + yMax = 0; + } else { + SW_FT_Vector* vec = outline->points; + SW_FT_Vector* limit = vec + outline->n_points; + + xMin = xMax = vec->x; + yMin = yMax = vec->y; + vec++; + + for (; vec < limit; vec++) { + SW_FT_Pos x, y; + + x = vec->x; + if (x < xMin) xMin = x; + if (x > xMax) xMax = x; + + y = vec->y; + if (y < yMin) yMin = y; + if (y > yMax) yMax = y; + } } - } - acbox->xMin = xMin; - acbox->xMax = xMax; - acbox->yMin = yMin; - acbox->yMax = yMax; + acbox->xMin = xMin; + acbox->xMax = xMax; + acbox->yMin = yMin; + acbox->yMax = yMax; } - } - +} +static SW_FT_Error ft_stroke_border_grow(SW_FT_StrokeBorder border, + SW_FT_UInt new_points) +{ + SW_FT_UInt old_max = border->max_points; + SW_FT_UInt new_max = border->num_points + new_points; + SW_FT_Error error = 0; - static SW_FT_Error - ft_stroke_border_grow( SW_FT_StrokeBorder border, - SW_FT_UInt new_points ) - { - SW_FT_UInt old_max = border->max_points; - SW_FT_UInt new_max = border->num_points + new_points; - SW_FT_Error error = 0; - - - if ( new_max > old_max ) - { - SW_FT_UInt cur_max = old_max; + if (new_max > old_max) { + SW_FT_UInt cur_max = old_max; + while (cur_max < new_max) cur_max += (cur_max >> 1) + 16; - while ( cur_max < new_max ) - cur_max += ( cur_max >> 1 ) + 16; + border->points = (SW_FT_Vector*)realloc(border->points, + cur_max * sizeof(SW_FT_Vector)); + border->tags = + (SW_FT_Byte*)realloc(border->tags, cur_max * sizeof(SW_FT_Byte)); - border->points = (SW_FT_Vector *) realloc(border->points, cur_max * sizeof(SW_FT_Vector)); - border->tags = (SW_FT_Byte *) realloc(border->tags, cur_max * sizeof(SW_FT_Byte)); + if (!border->points || !border->tags) goto Exit; - if ( !border->points || !border->tags) - goto Exit; - - border->max_points = cur_max; + border->max_points = cur_max; } - Exit: +Exit: return error; - } - +} - static void - ft_stroke_border_close( SW_FT_StrokeBorder border, - SW_FT_Bool reverse ) - { - SW_FT_UInt start = border->start; - SW_FT_UInt count = border->num_points; +static void ft_stroke_border_close(SW_FT_StrokeBorder border, + SW_FT_Bool reverse) +{ + SW_FT_UInt start = border->start; + SW_FT_UInt count = border->num_points; - - assert( border->start >= 0 ); + assert(border->start >= 0); /* don't record empty paths! */ - if ( count <= start + 1U ) - border->num_points = start; - else - { - /* copy the last point to the start of this sub-path, since */ - /* it contains the `adjusted' starting coordinates */ - border->num_points = --count; - border->points[start] = border->points[count]; - - if ( reverse ) - { - /* reverse the points */ - { - SW_FT_Vector* vec1 = border->points + start + 1; - SW_FT_Vector* vec2 = border->points + count - 1; - - - for ( ; vec1 < vec2; vec1++, vec2-- ) - { - SW_FT_Vector tmp; - - - tmp = *vec1; - *vec1 = *vec2; - *vec2 = tmp; - } - } + if (count <= start + 1U) + border->num_points = start; + else { + /* copy the last point to the start of this sub-path, since */ + /* it contains the `adjusted' starting coordinates */ + border->num_points = --count; + border->points[start] = border->points[count]; + + if (reverse) { + /* reverse the points */ + { + SW_FT_Vector* vec1 = border->points + start + 1; + SW_FT_Vector* vec2 = border->points + count - 1; - /* then the tags */ - { - SW_FT_Byte* tag1 = border->tags + start + 1; - SW_FT_Byte* tag2 = border->tags + count - 1; + for (; vec1 < vec2; vec1++, vec2--) { + SW_FT_Vector tmp; + tmp = *vec1; + *vec1 = *vec2; + *vec2 = tmp; + } + } - for ( ; tag1 < tag2; tag1++, tag2-- ) - { - SW_FT_Byte tmp; + /* then the tags */ + { + SW_FT_Byte* tag1 = border->tags + start + 1; + SW_FT_Byte* tag2 = border->tags + count - 1; + for (; tag1 < tag2; tag1++, tag2--) { + SW_FT_Byte tmp; - tmp = *tag1; - *tag1 = *tag2; - *tag2 = tmp; - } + tmp = *tag1; + *tag1 = *tag2; + *tag2 = tmp; + } + } } - } - border->tags[start ] |= SW_FT_STROKE_TAG_BEGIN; - border->tags[count - 1] |= SW_FT_STROKE_TAG_END; + border->tags[start] |= SW_FT_STROKE_TAG_BEGIN; + border->tags[count - 1] |= SW_FT_STROKE_TAG_END; } - border->start = -1; + border->start = -1; border->movable = FALSE; - } - - - static SW_FT_Error - ft_stroke_border_lineto( SW_FT_StrokeBorder border, - SW_FT_Vector* to, - SW_FT_Bool movable ) - { - SW_FT_Error error = 0; - - - assert( border->start >= 0 ); - - if ( border->movable ) - { - /* move last point */ - border->points[border->num_points - 1] = *to; - } - else - { - /* don't add zero-length lineto */ - if ( border->num_points > 0 && - SW_FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) && - SW_FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) ) - return error; - - /* add one point */ - error = ft_stroke_border_grow( border, 1 ); - if ( !error ) - { - SW_FT_Vector* vec = border->points + border->num_points; - SW_FT_Byte* tag = border->tags + border->num_points; - - - vec[0] = *to; - tag[0] = SW_FT_STROKE_TAG_ON; - - border->num_points += 1; - } +} + +static SW_FT_Error ft_stroke_border_lineto(SW_FT_StrokeBorder border, + SW_FT_Vector* to, SW_FT_Bool movable) +{ + SW_FT_Error error = 0; + + assert(border->start >= 0); + + if (border->movable) { + /* move last point */ + border->points[border->num_points - 1] = *to; + } else { + /* don't add zero-length lineto */ + if (border->num_points > 0 && + SW_FT_IS_SMALL(border->points[border->num_points - 1].x - to->x) && + SW_FT_IS_SMALL(border->points[border->num_points - 1].y - to->y)) + return error; + + /* add one point */ + error = ft_stroke_border_grow(border, 1); + if (!error) { + SW_FT_Vector* vec = border->points + border->num_points; + SW_FT_Byte* tag = border->tags + border->num_points; + + vec[0] = *to; + tag[0] = SW_FT_STROKE_TAG_ON; + + border->num_points += 1; + } } border->movable = movable; return error; - } - +} - static SW_FT_Error - ft_stroke_border_conicto( SW_FT_StrokeBorder border, - SW_FT_Vector* control, - SW_FT_Vector* to ) - { - SW_FT_Error error; +static SW_FT_Error ft_stroke_border_conicto(SW_FT_StrokeBorder border, + SW_FT_Vector* control, + SW_FT_Vector* to) +{ + SW_FT_Error error; + assert(border->start >= 0); - assert( border->start >= 0 ); - - error = ft_stroke_border_grow( border, 2 ); - if ( !error ) - { - SW_FT_Vector* vec = border->points + border->num_points; - SW_FT_Byte* tag = border->tags + border->num_points; - + error = ft_stroke_border_grow(border, 2); + if (!error) { + SW_FT_Vector* vec = border->points + border->num_points; + SW_FT_Byte* tag = border->tags + border->num_points; - vec[0] = *control; - vec[1] = *to; + vec[0] = *control; + vec[1] = *to; - tag[0] = 0; - tag[1] = SW_FT_STROKE_TAG_ON; + tag[0] = 0; + tag[1] = SW_FT_STROKE_TAG_ON; - border->num_points += 2; + border->num_points += 2; } border->movable = FALSE; return error; - } +} +static SW_FT_Error ft_stroke_border_cubicto(SW_FT_StrokeBorder border, + SW_FT_Vector* control1, + SW_FT_Vector* control2, + SW_FT_Vector* to) +{ + SW_FT_Error error; - static SW_FT_Error - ft_stroke_border_cubicto( SW_FT_StrokeBorder border, - SW_FT_Vector* control1, - SW_FT_Vector* control2, - SW_FT_Vector* to ) - { - SW_FT_Error error; + assert(border->start >= 0); + error = ft_stroke_border_grow(border, 3); + if (!error) { + SW_FT_Vector* vec = border->points + border->num_points; + SW_FT_Byte* tag = border->tags + border->num_points; - assert( border->start >= 0 ); + vec[0] = *control1; + vec[1] = *control2; + vec[2] = *to; - error = ft_stroke_border_grow( border, 3 ); - if ( !error ) - { - SW_FT_Vector* vec = border->points + border->num_points; - SW_FT_Byte* tag = border->tags + border->num_points; - - - vec[0] = *control1; - vec[1] = *control2; - vec[2] = *to; + tag[0] = SW_FT_STROKE_TAG_CUBIC; + tag[1] = SW_FT_STROKE_TAG_CUBIC; + tag[2] = SW_FT_STROKE_TAG_ON; - tag[0] = SW_FT_STROKE_TAG_CUBIC; - tag[1] = SW_FT_STROKE_TAG_CUBIC; - tag[2] = SW_FT_STROKE_TAG_ON; - - border->num_points += 3; + border->num_points += 3; } border->movable = FALSE; return error; - } +} + +#define SW_FT_ARC_CUBIC_ANGLE (SW_FT_ANGLE_PI / 2) + +static SW_FT_Error ft_stroke_border_arcto(SW_FT_StrokeBorder border, + SW_FT_Vector* center, + SW_FT_Fixed radius, + SW_FT_Angle angle_start, + SW_FT_Angle angle_diff) +{ + SW_FT_Angle total, angle, step, rotate, next, theta; + SW_FT_Vector a, b, a2, b2; + SW_FT_Fixed length; + SW_FT_Error error = 0; + /* compute start point */ + SW_FT_Vector_From_Polar(&a, radius, angle_start); + a.x += center->x; + a.y += center->y; -#define SW_FT_ARC_CUBIC_ANGLE ( SW_FT_ANGLE_PI / 2 ) + total = angle_diff; + angle = angle_start; + rotate = (angle_diff >= 0) ? SW_FT_ANGLE_PI2 : -SW_FT_ANGLE_PI2; + while (total != 0) { + step = total; + if (step > SW_FT_ARC_CUBIC_ANGLE) + step = SW_FT_ARC_CUBIC_ANGLE; - static SW_FT_Error - ft_stroke_border_arcto( SW_FT_StrokeBorder border, - SW_FT_Vector* center, - SW_FT_Fixed radius, - SW_FT_Angle angle_start, - SW_FT_Angle angle_diff ) - { - SW_FT_Angle total, angle, step, rotate, next, theta; - SW_FT_Vector a, b, a2, b2; - SW_FT_Fixed length; - SW_FT_Error error = 0; + else if (step < -SW_FT_ARC_CUBIC_ANGLE) + step = -SW_FT_ARC_CUBIC_ANGLE; + next = angle + step; + theta = step; + if (theta < 0) theta = -theta; - /* compute start point */ - SW_FT_Vector_From_Polar( &a, radius, angle_start ); - a.x += center->x; - a.y += center->y; + theta >>= 1; - total = angle_diff; - angle = angle_start; - rotate = ( angle_diff >= 0 ) ? SW_FT_ANGLE_PI2 : -SW_FT_ANGLE_PI2; + /* compute end point */ + SW_FT_Vector_From_Polar(&b, radius, next); + b.x += center->x; + b.y += center->y; - while ( total != 0 ) - { - step = total; - if ( step > SW_FT_ARC_CUBIC_ANGLE ) - step = SW_FT_ARC_CUBIC_ANGLE; - - else if ( step < -SW_FT_ARC_CUBIC_ANGLE ) - step = -SW_FT_ARC_CUBIC_ANGLE; - - next = angle + step; - theta = step; - if ( theta < 0 ) - theta = -theta; - - theta >>= 1; - - /* compute end point */ - SW_FT_Vector_From_Polar( &b, radius, next ); - b.x += center->x; - b.y += center->y; - - /* compute first and second control points */ - length = SW_FT_MulDiv( radius, SW_FT_Sin( theta ) * 4, - ( 0x10000L + SW_FT_Cos( theta ) ) * 3 ); - - SW_FT_Vector_From_Polar( &a2, length, angle + rotate ); - a2.x += a.x; - a2.y += a.y; - - SW_FT_Vector_From_Polar( &b2, length, next - rotate ); - b2.x += b.x; - b2.y += b.y; - - /* add cubic arc */ - error = ft_stroke_border_cubicto( border, &a2, &b2, &b ); - if ( error ) - break; - - /* process the rest of the arc ?? */ - a = b; - total -= step; - angle = next; + /* compute first and second control points */ + length = SW_FT_MulDiv(radius, SW_FT_Sin(theta) * 4, + (0x10000L + SW_FT_Cos(theta)) * 3); + + SW_FT_Vector_From_Polar(&a2, length, angle + rotate); + a2.x += a.x; + a2.y += a.y; + + SW_FT_Vector_From_Polar(&b2, length, next - rotate); + b2.x += b.x; + b2.y += b.y; + + /* add cubic arc */ + error = ft_stroke_border_cubicto(border, &a2, &b2, &b); + if (error) break; + + /* process the rest of the arc ?? */ + a = b; + total -= step; + angle = next; } return error; - } - +} - static SW_FT_Error - ft_stroke_border_moveto( SW_FT_StrokeBorder border, - SW_FT_Vector* to ) - { +static SW_FT_Error ft_stroke_border_moveto(SW_FT_StrokeBorder border, + SW_FT_Vector* to) +{ /* close current open path if any ? */ - if ( border->start >= 0 ) - ft_stroke_border_close( border, FALSE ); + if (border->start >= 0) ft_stroke_border_close(border, FALSE); border->start = border->num_points; border->movable = FALSE; - return ft_stroke_border_lineto( border, to, FALSE ); - } - + return ft_stroke_border_lineto(border, to, FALSE); +} - static void - ft_stroke_border_init( SW_FT_StrokeBorder border) - { +static void ft_stroke_border_init(SW_FT_StrokeBorder border) +{ border->points = NULL; - border->tags = NULL; + border->tags = NULL; border->num_points = 0; border->max_points = 0; - border->start = -1; - border->valid = FALSE; - } + border->start = -1; + border->valid = FALSE; +} - - static void - ft_stroke_border_reset( SW_FT_StrokeBorder border ) - { +static void ft_stroke_border_reset(SW_FT_StrokeBorder border) +{ border->num_points = 0; - border->start = -1; - border->valid = FALSE; - } - - - static void - ft_stroke_border_done( SW_FT_StrokeBorder border ) - { + border->start = -1; + border->valid = FALSE; +} - free( border->points ); - free( border->tags ); +static void ft_stroke_border_done(SW_FT_StrokeBorder border) +{ + free(border->points); + free(border->tags); border->num_points = 0; border->max_points = 0; - border->start = -1; - border->valid = FALSE; - } - - - static SW_FT_Error - ft_stroke_border_get_counts( SW_FT_StrokeBorder border, - SW_FT_UInt *anum_points, - SW_FT_UInt *anum_contours ) - { - SW_FT_Error error = 0; - SW_FT_UInt num_points = 0; - SW_FT_UInt num_contours = 0; - - SW_FT_UInt count = border->num_points; - SW_FT_Vector* point = border->points; - SW_FT_Byte* tags = border->tags; - SW_FT_Int in_contour = 0; - - - for ( ; count > 0; count--, num_points++, point++, tags++ ) - { - if ( tags[0] & SW_FT_STROKE_TAG_BEGIN ) - { - if ( in_contour != 0 ) - goto Fail; - - in_contour = 1; - } - else if ( in_contour == 0 ) - goto Fail; - - if ( tags[0] & SW_FT_STROKE_TAG_END ) - { - in_contour = 0; - num_contours++; - } + border->start = -1; + border->valid = FALSE; +} + +static SW_FT_Error ft_stroke_border_get_counts(SW_FT_StrokeBorder border, + SW_FT_UInt* anum_points, + SW_FT_UInt* anum_contours) +{ + SW_FT_Error error = 0; + SW_FT_UInt num_points = 0; + SW_FT_UInt num_contours = 0; + + SW_FT_UInt count = border->num_points; + SW_FT_Vector* point = border->points; + SW_FT_Byte* tags = border->tags; + SW_FT_Int in_contour = 0; + + for (; count > 0; count--, num_points++, point++, tags++) { + if (tags[0] & SW_FT_STROKE_TAG_BEGIN) { + if (in_contour != 0) goto Fail; + + in_contour = 1; + } else if (in_contour == 0) + goto Fail; + + if (tags[0] & SW_FT_STROKE_TAG_END) { + in_contour = 0; + num_contours++; + } } - if ( in_contour != 0 ) - goto Fail; + if (in_contour != 0) goto Fail; border->valid = TRUE; - Exit: - *anum_points = num_points; +Exit: + *anum_points = num_points; *anum_contours = num_contours; return error; - Fail: - num_points = 0; +Fail: + num_points = 0; num_contours = 0; goto Exit; - } - +} - static void - ft_stroke_border_export( SW_FT_StrokeBorder border, - SW_FT_Outline* outline ) - { +static void ft_stroke_border_export(SW_FT_StrokeBorder border, + SW_FT_Outline* outline) +{ /* copy point locations */ - memcpy( outline->points + outline->n_points, - border->points, - border->num_points * sizeof(SW_FT_Vector)); + memcpy(outline->points + outline->n_points, border->points, + border->num_points * sizeof(SW_FT_Vector)); /* copy tags */ { - SW_FT_UInt count = border->num_points; - SW_FT_Byte* read = border->tags; - SW_FT_Byte* write = (SW_FT_Byte*)outline->tags + outline->n_points; - - - for ( ; count > 0; count--, read++, write++ ) - { - if ( *read & SW_FT_STROKE_TAG_ON ) - *write = SW_FT_CURVE_TAG_ON; - else if ( *read & SW_FT_STROKE_TAG_CUBIC ) - *write = SW_FT_CURVE_TAG_CUBIC; - else - *write = SW_FT_CURVE_TAG_CONIC; - } + SW_FT_UInt count = border->num_points; + SW_FT_Byte* read = border->tags; + SW_FT_Byte* write = (SW_FT_Byte*)outline->tags + outline->n_points; + + for (; count > 0; count--, read++, write++) { + if (*read & SW_FT_STROKE_TAG_ON) + *write = SW_FT_CURVE_TAG_ON; + else if (*read & SW_FT_STROKE_TAG_CUBIC) + *write = SW_FT_CURVE_TAG_CUBIC; + else + *write = SW_FT_CURVE_TAG_CONIC; + } } /* copy contours */ { - SW_FT_UInt count = border->num_points; - SW_FT_Byte* tags = border->tags; - SW_FT_Short* write = outline->contours + outline->n_contours; - SW_FT_Short idx = (SW_FT_Short)outline->n_points; - - - for ( ; count > 0; count--, tags++, idx++ ) - { - if ( *tags & SW_FT_STROKE_TAG_END ) - { - *write++ = idx; - outline->n_contours++; + SW_FT_UInt count = border->num_points; + SW_FT_Byte* tags = border->tags; + SW_FT_Short* write = outline->contours + outline->n_contours; + SW_FT_Short idx = (SW_FT_Short)outline->n_points; + + for (; count > 0; count--, tags++, idx++) { + if (*tags & SW_FT_STROKE_TAG_END) { + *write++ = idx; + outline->n_contours++; + } } - } } - outline->n_points = (short)( outline->n_points + border->num_points ); - - assert( SW_FT_Outline_Check( outline ) == 0 ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** STROKER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - -#define SW_FT_SIDE_TO_ROTATE( s ) ( SW_FT_ANGLE_PI2 - (s) * SW_FT_ANGLE_PI ) - - typedef struct SW_FT_StrokerRec_ - { - SW_FT_Angle angle_in; /* direction into curr join */ - SW_FT_Angle angle_out; /* direction out of join */ - SW_FT_Vector center; /* current position */ - SW_FT_Fixed line_length; /* length of last lineto */ - SW_FT_Bool first_point; /* is this the start? */ - SW_FT_Bool subpath_open; /* is the subpath open? */ - SW_FT_Angle subpath_angle; /* subpath start direction */ - SW_FT_Vector subpath_start; /* subpath start position */ - SW_FT_Fixed subpath_line_length; /* subpath start lineto len */ - SW_FT_Bool handle_wide_strokes; /* use wide strokes logic? */ - - SW_FT_Stroker_LineCap line_cap; - SW_FT_Stroker_LineJoin line_join; - SW_FT_Stroker_LineJoin line_join_saved; - SW_FT_Fixed miter_limit; - SW_FT_Fixed radius; - - SW_FT_StrokeBorderRec borders[2]; - } SW_FT_StrokerRec; - - - /* documentation is in ftstroke.h */ - - SW_FT_Error - SW_FT_Stroker_New( SW_FT_Stroker *astroker ) - { - SW_FT_Error error = 0; /* assigned in SW_FT_NEW */ - SW_FT_Stroker stroker = NULL; - - - stroker = (SW_FT_StrokerRec *) calloc(1, sizeof(SW_FT_StrokerRec)); - if ( stroker ) - { - - ft_stroke_border_init( &stroker->borders[0]); - ft_stroke_border_init( &stroker->borders[1]); + outline->n_points = (short)(outline->n_points + border->num_points); + + assert(SW_FT_Outline_Check(outline) == 0); +} + +/*************************************************************************/ +/*************************************************************************/ +/***** *****/ +/***** STROKER *****/ +/***** *****/ +/*************************************************************************/ +/*************************************************************************/ + +#define SW_FT_SIDE_TO_ROTATE(s) (SW_FT_ANGLE_PI2 - (s)*SW_FT_ANGLE_PI) + +typedef struct SW_FT_StrokerRec_ { + SW_FT_Angle angle_in; /* direction into curr join */ + SW_FT_Angle angle_out; /* direction out of join */ + SW_FT_Vector center; /* current position */ + SW_FT_Fixed line_length; /* length of last lineto */ + SW_FT_Bool first_point; /* is this the start? */ + SW_FT_Bool subpath_open; /* is the subpath open? */ + SW_FT_Angle subpath_angle; /* subpath start direction */ + SW_FT_Vector subpath_start; /* subpath start position */ + SW_FT_Fixed subpath_line_length; /* subpath start lineto len */ + SW_FT_Bool handle_wide_strokes; /* use wide strokes logic? */ + + SW_FT_Stroker_LineCap line_cap; + SW_FT_Stroker_LineJoin line_join; + SW_FT_Stroker_LineJoin line_join_saved; + SW_FT_Fixed miter_limit; + SW_FT_Fixed radius; + + SW_FT_StrokeBorderRec borders[2]; +} SW_FT_StrokerRec; + +/* documentation is in ftstroke.h */ + +SW_FT_Error SW_FT_Stroker_New(SW_FT_Stroker* astroker) +{ + SW_FT_Error error = 0; /* assigned in SW_FT_NEW */ + SW_FT_Stroker stroker = NULL; + + stroker = (SW_FT_StrokerRec*)calloc(1, sizeof(SW_FT_StrokerRec)); + if (stroker) { + ft_stroke_border_init(&stroker->borders[0]); + ft_stroke_border_init(&stroker->borders[1]); } *astroker = stroker; return error; - } +} - void - SW_FT_Stroker_Rewind( SW_FT_Stroker stroker ) - { - if ( stroker ) - { - ft_stroke_border_reset( &stroker->borders[0] ); - ft_stroke_border_reset( &stroker->borders[1] ); +void SW_FT_Stroker_Rewind(SW_FT_Stroker stroker) +{ + if (stroker) { + ft_stroke_border_reset(&stroker->borders[0]); + ft_stroke_border_reset(&stroker->borders[1]); } - } - - - /* documentation is in ftstroke.h */ - - void - SW_FT_Stroker_Set( SW_FT_Stroker stroker, - SW_FT_Fixed radius, - SW_FT_Stroker_LineCap line_cap, - SW_FT_Stroker_LineJoin line_join, - SW_FT_Fixed miter_limit ) - { - stroker->radius = radius; - stroker->line_cap = line_cap; - stroker->line_join = line_join; +} + +/* documentation is in ftstroke.h */ + +void SW_FT_Stroker_Set(SW_FT_Stroker stroker, SW_FT_Fixed radius, + SW_FT_Stroker_LineCap line_cap, + SW_FT_Stroker_LineJoin line_join, + SW_FT_Fixed miter_limit) +{ + stroker->radius = radius; + stroker->line_cap = line_cap; + stroker->line_join = line_join; stroker->miter_limit = miter_limit; /* ensure miter limit has sensible value */ - if ( stroker->miter_limit < 0x10000 ) - stroker->miter_limit = 0x10000; + if (stroker->miter_limit < 0x10000) stroker->miter_limit = 0x10000; /* save line join style: */ /* line join style can be temporarily changed when stroking curves */ stroker->line_join_saved = line_join; - SW_FT_Stroker_Rewind( stroker ); - } + SW_FT_Stroker_Rewind(stroker); +} - /* documentation is in ftstroke.h */ +/* documentation is in ftstroke.h */ - void - SW_FT_Stroker_Done( SW_FT_Stroker stroker ) - { - if ( stroker ) - { - - ft_stroke_border_done( &stroker->borders[0] ); - ft_stroke_border_done( &stroker->borders[1] ); +void SW_FT_Stroker_Done(SW_FT_Stroker stroker) +{ + if (stroker) { + ft_stroke_border_done(&stroker->borders[0]); + ft_stroke_border_done(&stroker->borders[1]); - free( stroker ); + free(stroker); } - } - +} - /* create a circular arc at a corner or cap */ - static SW_FT_Error - ft_stroker_arcto( SW_FT_Stroker stroker, - SW_FT_Int side ) - { - SW_FT_Angle total, rotate; - SW_FT_Fixed radius = stroker->radius; - SW_FT_Error error = 0; - SW_FT_StrokeBorder border = stroker->borders + side; +/* create a circular arc at a corner or cap */ +static SW_FT_Error ft_stroker_arcto(SW_FT_Stroker stroker, SW_FT_Int side) +{ + SW_FT_Angle total, rotate; + SW_FT_Fixed radius = stroker->radius; + SW_FT_Error error = 0; + SW_FT_StrokeBorder border = stroker->borders + side; + rotate = SW_FT_SIDE_TO_ROTATE(side); - rotate = SW_FT_SIDE_TO_ROTATE( side ); + total = SW_FT_Angle_Diff(stroker->angle_in, stroker->angle_out); + if (total == SW_FT_ANGLE_PI) total = -rotate * 2; - total = SW_FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); - if ( total == SW_FT_ANGLE_PI ) - total = -rotate * 2; - - error = ft_stroke_border_arcto( border, - &stroker->center, - radius, - stroker->angle_in + rotate, - total ); + error = ft_stroke_border_arcto(border, &stroker->center, radius, + stroker->angle_in + rotate, total); border->movable = FALSE; return error; - } - - - /* add a cap at the end of an opened path */ - static SW_FT_Error - ft_stroker_cap( SW_FT_Stroker stroker, - SW_FT_Angle angle, - SW_FT_Int side ) - { - SW_FT_Error error = 0; - +} - if ( stroker->line_cap == SW_FT_STROKER_LINECAP_ROUND ) - { - /* add a round cap */ - stroker->angle_in = angle; - stroker->angle_out = angle + SW_FT_ANGLE_PI; +/* add a cap at the end of an opened path */ +static SW_FT_Error ft_stroker_cap(SW_FT_Stroker stroker, SW_FT_Angle angle, + SW_FT_Int side) +{ + SW_FT_Error error = 0; - error = ft_stroker_arcto( stroker, side ); - } - else if ( stroker->line_cap == SW_FT_STROKER_LINECAP_SQUARE ) - { - /* add a square cap */ - SW_FT_Vector delta, delta2; - SW_FT_Angle rotate = SW_FT_SIDE_TO_ROTATE( side ); - SW_FT_Fixed radius = stroker->radius; - SW_FT_StrokeBorder border = stroker->borders + side; + if (stroker->line_cap == SW_FT_STROKER_LINECAP_ROUND) { + /* add a round cap */ + stroker->angle_in = angle; + stroker->angle_out = angle + SW_FT_ANGLE_PI; + error = ft_stroker_arcto(stroker, side); + } else if (stroker->line_cap == SW_FT_STROKER_LINECAP_SQUARE) { + /* add a square cap */ + SW_FT_Vector delta, delta2; + SW_FT_Angle rotate = SW_FT_SIDE_TO_ROTATE(side); + SW_FT_Fixed radius = stroker->radius; + SW_FT_StrokeBorder border = stroker->borders + side; - SW_FT_Vector_From_Polar( &delta2, radius, angle + rotate ); - SW_FT_Vector_From_Polar( &delta, radius, angle ); + SW_FT_Vector_From_Polar(&delta2, radius, angle + rotate); + SW_FT_Vector_From_Polar(&delta, radius, angle); - delta.x += stroker->center.x + delta2.x; - delta.y += stroker->center.y + delta2.y; + delta.x += stroker->center.x + delta2.x; + delta.y += stroker->center.y + delta2.y; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; + error = ft_stroke_border_lineto(border, &delta, FALSE); + if (error) goto Exit; - SW_FT_Vector_From_Polar( &delta2, radius, angle - rotate ); - SW_FT_Vector_From_Polar( &delta, radius, angle ); + SW_FT_Vector_From_Polar(&delta2, radius, angle - rotate); + SW_FT_Vector_From_Polar(&delta, radius, angle); - delta.x += delta2.x + stroker->center.x; - delta.y += delta2.y + stroker->center.y; + delta.x += delta2.x + stroker->center.x; + delta.y += delta2.y + stroker->center.y; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - } - else if ( stroker->line_cap == SW_FT_STROKER_LINECAP_BUTT ) - { - /* add a butt ending */ - SW_FT_Vector delta; - SW_FT_Angle rotate = SW_FT_SIDE_TO_ROTATE( side ); - SW_FT_Fixed radius = stroker->radius; - SW_FT_StrokeBorder border = stroker->borders + side; + error = ft_stroke_border_lineto(border, &delta, FALSE); + } else if (stroker->line_cap == SW_FT_STROKER_LINECAP_BUTT) { + /* add a butt ending */ + SW_FT_Vector delta; + SW_FT_Angle rotate = SW_FT_SIDE_TO_ROTATE(side); + SW_FT_Fixed radius = stroker->radius; + SW_FT_StrokeBorder border = stroker->borders + side; + SW_FT_Vector_From_Polar(&delta, radius, angle + rotate); - SW_FT_Vector_From_Polar( &delta, radius, angle + rotate ); + delta.x += stroker->center.x; + delta.y += stroker->center.y; - delta.x += stroker->center.x; - delta.y += stroker->center.y; + error = ft_stroke_border_lineto(border, &delta, FALSE); + if (error) goto Exit; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; + SW_FT_Vector_From_Polar(&delta, radius, angle - rotate); - SW_FT_Vector_From_Polar( &delta, radius, angle - rotate ); - - delta.x += stroker->center.x; - delta.y += stroker->center.y; + delta.x += stroker->center.x; + delta.y += stroker->center.y; - error = ft_stroke_border_lineto( border, &delta, FALSE ); + error = ft_stroke_border_lineto(border, &delta, FALSE); } - Exit: +Exit: return error; - } - - - /* process an inside corner, i.e. compute intersection */ - static SW_FT_Error - ft_stroker_inside( SW_FT_Stroker stroker, - SW_FT_Int side, - SW_FT_Fixed line_length ) - { - SW_FT_StrokeBorder border = stroker->borders + side; - SW_FT_Angle phi, theta, rotate; - SW_FT_Fixed length, thcos; - SW_FT_Vector delta; - SW_FT_Error error = 0; - SW_FT_Bool intersect; /* use intersection of lines? */ +} +/* process an inside corner, i.e. compute intersection */ +static SW_FT_Error ft_stroker_inside(SW_FT_Stroker stroker, SW_FT_Int side, + SW_FT_Fixed line_length) +{ + SW_FT_StrokeBorder border = stroker->borders + side; + SW_FT_Angle phi, theta, rotate; + SW_FT_Fixed length, thcos; + SW_FT_Vector delta; + SW_FT_Error error = 0; + SW_FT_Bool intersect; /* use intersection of lines? */ - rotate = SW_FT_SIDE_TO_ROTATE( side ); + rotate = SW_FT_SIDE_TO_ROTATE(side); - theta = SW_FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2; + theta = SW_FT_Angle_Diff(stroker->angle_in, stroker->angle_out) / 2; /* Only intersect borders if between two lineto's and both */ /* lines are long enough (line_length is zero for curves). */ - if ( !border->movable || line_length == 0 ) - intersect = FALSE; - else - { - /* compute minimum required length of lines */ - SW_FT_Fixed min_length = ft_pos_abs( SW_FT_MulFix( stroker->radius, - SW_FT_Tan( theta ) ) ); - - - intersect = SW_FT_BOOL( stroker->line_length >= min_length && - line_length >= min_length ); + if (!border->movable || line_length == 0) + intersect = FALSE; + else { + /* compute minimum required length of lines */ + SW_FT_Fixed min_length = + ft_pos_abs(SW_FT_MulFix(stroker->radius, SW_FT_Tan(theta))); + + intersect = SW_FT_BOOL(stroker->line_length >= min_length && + line_length >= min_length); } - if ( !intersect ) - { - SW_FT_Vector_From_Polar( &delta, stroker->radius, - stroker->angle_out + rotate ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; + if (!intersect) { + SW_FT_Vector_From_Polar(&delta, stroker->radius, + stroker->angle_out + rotate); + delta.x += stroker->center.x; + delta.y += stroker->center.y; - border->movable = FALSE; - } - else - { - /* compute median angle */ - phi = stroker->angle_in + theta; + border->movable = FALSE; + } else { + /* compute median angle */ + phi = stroker->angle_in + theta; - thcos = SW_FT_Cos( theta ); + thcos = SW_FT_Cos(theta); - length = SW_FT_DivFix( stroker->radius, thcos ); + length = SW_FT_DivFix(stroker->radius, thcos); - SW_FT_Vector_From_Polar( &delta, length, phi + rotate ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; + SW_FT_Vector_From_Polar(&delta, length, phi + rotate); + delta.x += stroker->center.x; + delta.y += stroker->center.y; } - error = ft_stroke_border_lineto( border, &delta, FALSE ); + error = ft_stroke_border_lineto(border, &delta, FALSE); return error; - } - - - /* process an outside corner, i.e. compute bevel/miter/round */ - static SW_FT_Error - ft_stroker_outside( SW_FT_Stroker stroker, - SW_FT_Int side, - SW_FT_Fixed line_length ) - { - SW_FT_StrokeBorder border = stroker->borders + side; - SW_FT_Error error; - SW_FT_Angle rotate; - - - if ( stroker->line_join == SW_FT_STROKER_LINEJOIN_ROUND ) - error = ft_stroker_arcto( stroker, side ); - else - { - /* this is a mitered (pointed) or beveled (truncated) corner */ - SW_FT_Fixed sigma = 0, radius = stroker->radius; - SW_FT_Angle theta = 0, phi = 0; - SW_FT_Fixed thcos = 0; - SW_FT_Bool bevel, fixed_bevel; - - - rotate = SW_FT_SIDE_TO_ROTATE( side ); - - bevel = - SW_FT_BOOL( stroker->line_join == SW_FT_STROKER_LINEJOIN_BEVEL ); - - fixed_bevel = - SW_FT_BOOL( stroker->line_join != SW_FT_STROKER_LINEJOIN_MITER_VARIABLE ); +} + +/* process an outside corner, i.e. compute bevel/miter/round */ +static SW_FT_Error ft_stroker_outside(SW_FT_Stroker stroker, SW_FT_Int side, + SW_FT_Fixed line_length) +{ + SW_FT_StrokeBorder border = stroker->borders + side; + SW_FT_Error error; + SW_FT_Angle rotate; + + if (stroker->line_join == SW_FT_STROKER_LINEJOIN_ROUND) + error = ft_stroker_arcto(stroker, side); + else { + /* this is a mitered (pointed) or beveled (truncated) corner */ + SW_FT_Fixed sigma = 0, radius = stroker->radius; + SW_FT_Angle theta = 0, phi = 0; + SW_FT_Fixed thcos = 0; + SW_FT_Bool bevel, fixed_bevel; + + rotate = SW_FT_SIDE_TO_ROTATE(side); + + bevel = SW_FT_BOOL(stroker->line_join == SW_FT_STROKER_LINEJOIN_BEVEL); + + fixed_bevel = SW_FT_BOOL(stroker->line_join != + SW_FT_STROKER_LINEJOIN_MITER_VARIABLE); + + if (!bevel) { + theta = SW_FT_Angle_Diff(stroker->angle_in, stroker->angle_out); + + if (theta == SW_FT_ANGLE_PI) { + theta = rotate; + phi = stroker->angle_in; + } else { + theta /= 2; + phi = stroker->angle_in + theta + rotate; + } - if ( !bevel ) - { - theta = SW_FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); + thcos = SW_FT_Cos(theta); + sigma = SW_FT_MulFix(stroker->miter_limit, thcos); - if ( theta == SW_FT_ANGLE_PI ) - { - theta = rotate; - phi = stroker->angle_in; - } - else - { - theta /= 2; - phi = stroker->angle_in + theta + rotate; + /* is miter limit exceeded? */ + if (sigma < 0x10000L) { + /* don't create variable bevels for very small deviations; */ + /* SW_FT_Sin(x) = 0 for x <= 57 */ + if (fixed_bevel || ft_pos_abs(theta) > 57) bevel = TRUE; + } } - thcos = SW_FT_Cos( theta ); - sigma = SW_FT_MulFix( stroker->miter_limit, thcos ); - - /* is miter limit exceeded? */ - if ( sigma < 0x10000L ) + if (bevel) /* this is a bevel (broken angle) */ { - /* don't create variable bevels for very small deviations; */ - /* SW_FT_Sin(x) = 0 for x <= 57 */ - if ( fixed_bevel || ft_pos_abs( theta ) > 57 ) - bevel = TRUE; - } - } - - if ( bevel ) /* this is a bevel (broken angle) */ - { - if ( fixed_bevel ) + if (fixed_bevel) { + /* the outer corners are simply joined together */ + SW_FT_Vector delta; + + /* add bevel */ + SW_FT_Vector_From_Polar(&delta, radius, + stroker->angle_out + rotate); + delta.x += stroker->center.x; + delta.y += stroker->center.y; + + border->movable = FALSE; + error = ft_stroke_border_lineto(border, &delta, FALSE); + } else /* variable bevel */ + { + /* the miter is truncated */ + SW_FT_Vector middle, delta; + SW_FT_Fixed length; + + /* compute middle point */ + SW_FT_Vector_From_Polar( + &middle, SW_FT_MulFix(radius, stroker->miter_limit), phi); + middle.x += stroker->center.x; + middle.y += stroker->center.y; + + /* compute first angle point */ + length = SW_FT_MulDiv(radius, 0x10000L - sigma, + ft_pos_abs(SW_FT_Sin(theta))); + + SW_FT_Vector_From_Polar(&delta, length, phi + rotate); + delta.x += middle.x; + delta.y += middle.y; + + error = ft_stroke_border_lineto(border, &delta, FALSE); + if (error) goto Exit; + + /* compute second angle point */ + SW_FT_Vector_From_Polar(&delta, length, phi - rotate); + delta.x += middle.x; + delta.y += middle.y; + + error = ft_stroke_border_lineto(border, &delta, FALSE); + if (error) goto Exit; + + /* finally, add an end point; only needed if not lineto */ + /* (line_length is zero for curves) */ + if (line_length == 0) { + SW_FT_Vector_From_Polar(&delta, radius, + stroker->angle_out + rotate); + + delta.x += stroker->center.x; + delta.y += stroker->center.y; + + error = ft_stroke_border_lineto(border, &delta, FALSE); + } + } + } else /* this is a miter (intersection) */ { - /* the outer corners are simply joined together */ - SW_FT_Vector delta; + SW_FT_Fixed length; + SW_FT_Vector delta; + length = SW_FT_DivFix(stroker->radius, thcos); - /* add bevel */ - SW_FT_Vector_From_Polar( &delta, - radius, - stroker->angle_out + rotate ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; - - border->movable = FALSE; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - } - else /* variable bevel */ - { - /* the miter is truncated */ - SW_FT_Vector middle, delta; - SW_FT_Fixed length; - - - /* compute middle point */ - SW_FT_Vector_From_Polar( &middle, - SW_FT_MulFix( radius, stroker->miter_limit ), - phi ); - middle.x += stroker->center.x; - middle.y += stroker->center.y; - - /* compute first angle point */ - length = SW_FT_MulDiv( radius, 0x10000L - sigma, - ft_pos_abs( SW_FT_Sin( theta ) ) ); - - SW_FT_Vector_From_Polar( &delta, length, phi + rotate ); - delta.x += middle.x; - delta.y += middle.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - - /* compute second angle point */ - SW_FT_Vector_From_Polar( &delta, length, phi - rotate ); - delta.x += middle.x; - delta.y += middle.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - - /* finally, add an end point; only needed if not lineto */ - /* (line_length is zero for curves) */ - if ( line_length == 0 ) - { - SW_FT_Vector_From_Polar( &delta, - radius, - stroker->angle_out + rotate ); - + SW_FT_Vector_From_Polar(&delta, length, phi); delta.x += stroker->center.x; delta.y += stroker->center.y; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - } - } - } - else /* this is a miter (intersection) */ - { - SW_FT_Fixed length; - SW_FT_Vector delta; - + error = ft_stroke_border_lineto(border, &delta, FALSE); + if (error) goto Exit; - length = SW_FT_DivFix( stroker->radius, thcos ); - - SW_FT_Vector_From_Polar( &delta, length, phi ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; + /* now add an end point; only needed if not lineto */ + /* (line_length is zero for curves) */ + if (line_length == 0) { + SW_FT_Vector_From_Polar(&delta, stroker->radius, + stroker->angle_out + rotate); + delta.x += stroker->center.x; + delta.y += stroker->center.y; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - - /* now add an end point; only needed if not lineto */ - /* (line_length is zero for curves) */ - if ( line_length == 0 ) - { - SW_FT_Vector_From_Polar( &delta, - stroker->radius, - stroker->angle_out + rotate ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); + error = ft_stroke_border_lineto(border, &delta, FALSE); + } } - } } - Exit: +Exit: return error; - } +} +static SW_FT_Error ft_stroker_process_corner(SW_FT_Stroker stroker, + SW_FT_Fixed line_length) +{ + SW_FT_Error error = 0; + SW_FT_Angle turn; + SW_FT_Int inside_side; - static SW_FT_Error - ft_stroker_process_corner( SW_FT_Stroker stroker, - SW_FT_Fixed line_length ) - { - SW_FT_Error error = 0; - SW_FT_Angle turn; - SW_FT_Int inside_side; - - - turn = SW_FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); + turn = SW_FT_Angle_Diff(stroker->angle_in, stroker->angle_out); /* no specific corner processing is required if the turn is 0 */ - if ( turn == 0 ) - goto Exit; + if (turn == 0) goto Exit; /* when we turn to the right, the inside side is 0 */ inside_side = 0; /* otherwise, the inside side is 1 */ - if ( turn < 0 ) - inside_side = 1; + if (turn < 0) inside_side = 1; /* process the inside side */ - error = ft_stroker_inside( stroker, inside_side, line_length ); - if ( error ) - goto Exit; + error = ft_stroker_inside(stroker, inside_side, line_length); + if (error) goto Exit; /* process the outside side */ - error = ft_stroker_outside( stroker, 1 - inside_side, line_length ); + error = ft_stroker_outside(stroker, 1 - inside_side, line_length); - Exit: +Exit: return error; - } - - - /* add two points to the left and right borders corresponding to the */ - /* start of the subpath */ - static SW_FT_Error - ft_stroker_subpath_start( SW_FT_Stroker stroker, - SW_FT_Angle start_angle, - SW_FT_Fixed line_length ) - { - SW_FT_Vector delta; - SW_FT_Vector point; - SW_FT_Error error; - SW_FT_StrokeBorder border; - - - SW_FT_Vector_From_Polar( &delta, stroker->radius, - start_angle + SW_FT_ANGLE_PI2 ); +} + +/* add two points to the left and right borders corresponding to the */ +/* start of the subpath */ +static SW_FT_Error ft_stroker_subpath_start(SW_FT_Stroker stroker, + SW_FT_Angle start_angle, + SW_FT_Fixed line_length) +{ + SW_FT_Vector delta; + SW_FT_Vector point; + SW_FT_Error error; + SW_FT_StrokeBorder border; + + SW_FT_Vector_From_Polar(&delta, stroker->radius, + start_angle + SW_FT_ANGLE_PI2); point.x = stroker->center.x + delta.x; point.y = stroker->center.y + delta.y; border = stroker->borders; - error = ft_stroke_border_moveto( border, &point ); - if ( error ) - goto Exit; + error = ft_stroke_border_moveto(border, &point); + if (error) goto Exit; point.x = stroker->center.x - delta.x; point.y = stroker->center.y - delta.y; border++; - error = ft_stroke_border_moveto( border, &point ); + error = ft_stroke_border_moveto(border, &point); /* save angle, position, and line length for last join */ /* (line_length is zero for curves) */ - stroker->subpath_angle = start_angle; - stroker->first_point = FALSE; + stroker->subpath_angle = start_angle; + stroker->first_point = FALSE; stroker->subpath_line_length = line_length; - Exit: +Exit: return error; - } +} +/* documentation is in ftstroke.h */ - /* documentation is in ftstroke.h */ - - SW_FT_Error - SW_FT_Stroker_LineTo( SW_FT_Stroker stroker, - SW_FT_Vector* to ) - { - SW_FT_Error error = 0; - SW_FT_StrokeBorder border; - SW_FT_Vector delta; - SW_FT_Angle angle; - SW_FT_Int side; - SW_FT_Fixed line_length; - +SW_FT_Error SW_FT_Stroker_LineTo(SW_FT_Stroker stroker, SW_FT_Vector* to) +{ + SW_FT_Error error = 0; + SW_FT_StrokeBorder border; + SW_FT_Vector delta; + SW_FT_Angle angle; + SW_FT_Int side; + SW_FT_Fixed line_length; delta.x = to->x - stroker->center.x; delta.y = to->y - stroker->center.y; /* a zero-length lineto is a no-op; avoid creating a spurious corner */ - if ( delta.x == 0 && delta.y == 0 ) - goto Exit; + if (delta.x == 0 && delta.y == 0) goto Exit; /* compute length of line */ - line_length = SW_FT_Vector_Length( &delta ); + line_length = SW_FT_Vector_Length(&delta); - angle = SW_FT_Atan2( delta.x, delta.y ); - SW_FT_Vector_From_Polar( &delta, stroker->radius, angle + SW_FT_ANGLE_PI2 ); + angle = SW_FT_Atan2(delta.x, delta.y); + SW_FT_Vector_From_Polar(&delta, stroker->radius, angle + SW_FT_ANGLE_PI2); /* process corner if necessary */ - if ( stroker->first_point ) - { - /* This is the first segment of a subpath. We need to */ - /* add a point to each border at their respective starting */ - /* point locations. */ - error = ft_stroker_subpath_start( stroker, angle, line_length ); - if ( error ) - goto Exit; - } - else - { - /* process the current corner */ - stroker->angle_out = angle; - error = ft_stroker_process_corner( stroker, line_length ); - if ( error ) - goto Exit; + if (stroker->first_point) { + /* This is the first segment of a subpath. We need to */ + /* add a point to each border at their respective starting */ + /* point locations. */ + error = ft_stroker_subpath_start(stroker, angle, line_length); + if (error) goto Exit; + } else { + /* process the current corner */ + stroker->angle_out = angle; + error = ft_stroker_process_corner(stroker, line_length); + if (error) goto Exit; } /* now add a line segment to both the `inside' and `outside' paths */ - for ( border = stroker->borders, side = 1; side >= 0; side--, border++ ) - { - SW_FT_Vector point; - + for (border = stroker->borders, side = 1; side >= 0; side--, border++) { + SW_FT_Vector point; - point.x = to->x + delta.x; - point.y = to->y + delta.y; + point.x = to->x + delta.x; + point.y = to->y + delta.y; - /* the ends of lineto borders are movable */ - error = ft_stroke_border_lineto( border, &point, TRUE ); - if ( error ) - goto Exit; + /* the ends of lineto borders are movable */ + error = ft_stroke_border_lineto(border, &point, TRUE); + if (error) goto Exit; - delta.x = -delta.x; - delta.y = -delta.y; + delta.x = -delta.x; + delta.y = -delta.y; } - stroker->angle_in = angle; - stroker->center = *to; + stroker->angle_in = angle; + stroker->center = *to; stroker->line_length = line_length; - Exit: +Exit: return error; - } - +} - /* documentation is in ftstroke.h */ - - SW_FT_Error - SW_FT_Stroker_ConicTo( SW_FT_Stroker stroker, - SW_FT_Vector* control, - SW_FT_Vector* to ) - { - SW_FT_Error error = 0; - SW_FT_Vector bez_stack[34]; - SW_FT_Vector* arc; - SW_FT_Vector* limit = bez_stack + 30; - SW_FT_Bool first_arc = TRUE; +/* documentation is in ftstroke.h */ +SW_FT_Error SW_FT_Stroker_ConicTo(SW_FT_Stroker stroker, SW_FT_Vector* control, + SW_FT_Vector* to) +{ + SW_FT_Error error = 0; + SW_FT_Vector bez_stack[34]; + SW_FT_Vector* arc; + SW_FT_Vector* limit = bez_stack + 30; + SW_FT_Bool first_arc = TRUE; /* if all control points are coincident, this is a no-op; */ /* avoid creating a spurious corner */ - if ( SW_FT_IS_SMALL( stroker->center.x - control->x ) && - SW_FT_IS_SMALL( stroker->center.y - control->y ) && - SW_FT_IS_SMALL( control->x - to->x ) && - SW_FT_IS_SMALL( control->y - to->y ) ) - { - stroker->center = *to; - goto Exit; + if (SW_FT_IS_SMALL(stroker->center.x - control->x) && + SW_FT_IS_SMALL(stroker->center.y - control->y) && + SW_FT_IS_SMALL(control->x - to->x) && + SW_FT_IS_SMALL(control->y - to->y)) { + stroker->center = *to; + goto Exit; } - arc = bez_stack; + arc = bez_stack; arc[0] = *to; arc[1] = *control; arc[2] = stroker->center; - while ( arc >= bez_stack ) - { - SW_FT_Angle angle_in, angle_out; + while (arc >= bez_stack) { + SW_FT_Angle angle_in, angle_out; + /* initialize with current direction */ + angle_in = angle_out = stroker->angle_in; - /* initialize with current direction */ - angle_in = angle_out = stroker->angle_in; + if (arc < limit && + !ft_conic_is_small_enough(arc, &angle_in, &angle_out)) { + if (stroker->first_point) stroker->angle_in = angle_in; - if ( arc < limit && - !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) ) - { - if ( stroker->first_point ) - stroker->angle_in = angle_in; - - ft_conic_split( arc ); - arc += 2; - continue; - } - - if ( first_arc ) - { - first_arc = FALSE; - - /* process corner if necessary */ - if ( stroker->first_point ) - error = ft_stroker_subpath_start( stroker, angle_in, 0 ); - else - { - stroker->angle_out = angle_in; - error = ft_stroker_process_corner( stroker, 0 ); + ft_conic_split(arc); + arc += 2; + continue; } - } - else if ( ft_pos_abs( SW_FT_Angle_Diff( stroker->angle_in, angle_in ) ) > - SW_FT_SMALL_CONIC_THRESHOLD / 4 ) - { - /* if the deviation from one arc to the next is too great, */ - /* add a round corner */ - stroker->center = arc[2]; - stroker->angle_out = angle_in; - stroker->line_join = SW_FT_STROKER_LINEJOIN_ROUND; - - error = ft_stroker_process_corner( stroker, 0 ); - - /* reinstate line join style */ - stroker->line_join = stroker->line_join_saved; - } - - if ( error ) - goto Exit; - /* the arc's angle is small enough; we can add it directly to each */ - /* border */ - { - SW_FT_Vector ctrl, end; - SW_FT_Angle theta, phi, rotate, alpha0 = 0; - SW_FT_Fixed length; - SW_FT_StrokeBorder border; - SW_FT_Int side; + if (first_arc) { + first_arc = FALSE; + /* process corner if necessary */ + if (stroker->first_point) + error = ft_stroker_subpath_start(stroker, angle_in, 0); + else { + stroker->angle_out = angle_in; + error = ft_stroker_process_corner(stroker, 0); + } + } else if (ft_pos_abs(SW_FT_Angle_Diff(stroker->angle_in, angle_in)) > + SW_FT_SMALL_CONIC_THRESHOLD / 4) { + /* if the deviation from one arc to the next is too great, */ + /* add a round corner */ + stroker->center = arc[2]; + stroker->angle_out = angle_in; + stroker->line_join = SW_FT_STROKER_LINEJOIN_ROUND; + + error = ft_stroker_process_corner(stroker, 0); + + /* reinstate line join style */ + stroker->line_join = stroker->line_join_saved; + } - theta = SW_FT_Angle_Diff( angle_in, angle_out ) / 2; - phi = angle_in + theta; - length = SW_FT_DivFix( stroker->radius, SW_FT_Cos( theta ) ); - - /* compute direction of original arc */ - if ( stroker->handle_wide_strokes ) - alpha0 = SW_FT_Atan2( arc[0].x - arc[2].x, arc[0].y - arc[2].y ); + if (error) goto Exit; - for ( border = stroker->borders, side = 0; - side <= 1; - side++, border++ ) + /* the arc's angle is small enough; we can add it directly to each */ + /* border */ { - rotate = SW_FT_SIDE_TO_ROTATE( side ); - - /* compute control point */ - SW_FT_Vector_From_Polar( &ctrl, length, phi + rotate ); - ctrl.x += arc[1].x; - ctrl.y += arc[1].y; - - /* compute end point */ - SW_FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate ); - end.x += arc[0].x; - end.y += arc[0].y; - - if ( stroker->handle_wide_strokes ) - { - SW_FT_Vector start; - SW_FT_Angle alpha1; - - - /* determine whether the border radius is greater than the */ - /* radius of curvature of the original arc */ - start = border->points[border->num_points - 1]; - - alpha1 = SW_FT_Atan2( end.x - start.x, end.y - start.y ); - - /* is the direction of the border arc opposite to */ - /* that of the original arc? */ - if ( ft_pos_abs( SW_FT_Angle_Diff( alpha0, alpha1 ) ) > - SW_FT_ANGLE_PI / 2 ) - { - SW_FT_Angle beta, gamma; - SW_FT_Vector bvec, delta; - SW_FT_Fixed blen, sinA, sinB, alen; - - - /* use the sine rule to find the intersection point */ - beta = SW_FT_Atan2( arc[2].x - start.x, arc[2].y - start.y ); - gamma = SW_FT_Atan2( arc[0].x - end.x, arc[0].y - end.y ); - - bvec.x = end.x - start.x; - bvec.y = end.y - start.y; - - blen = SW_FT_Vector_Length( &bvec ); - - sinA = ft_pos_abs( SW_FT_Sin( alpha1 - gamma ) ); - sinB = ft_pos_abs( SW_FT_Sin( beta - gamma ) ); - - alen = SW_FT_MulDiv( blen, sinA, sinB ); - - SW_FT_Vector_From_Polar( &delta, alen, beta ); - delta.x += start.x; - delta.y += start.y; - - /* circumnavigate the negative sector backwards */ - border->movable = FALSE; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - error = ft_stroke_border_lineto( border, &end, FALSE ); - if ( error ) - goto Exit; - error = ft_stroke_border_conicto( border, &ctrl, &start ); - if ( error ) - goto Exit; - /* and then move to the endpoint */ - error = ft_stroke_border_lineto( border, &end, FALSE ); - if ( error ) - goto Exit; - - continue; + SW_FT_Vector ctrl, end; + SW_FT_Angle theta, phi, rotate, alpha0 = 0; + SW_FT_Fixed length; + SW_FT_StrokeBorder border; + SW_FT_Int side; + + theta = SW_FT_Angle_Diff(angle_in, angle_out) / 2; + phi = angle_in + theta; + length = SW_FT_DivFix(stroker->radius, SW_FT_Cos(theta)); + + /* compute direction of original arc */ + if (stroker->handle_wide_strokes) + alpha0 = SW_FT_Atan2(arc[0].x - arc[2].x, arc[0].y - arc[2].y); + + for (border = stroker->borders, side = 0; side <= 1; + side++, border++) { + rotate = SW_FT_SIDE_TO_ROTATE(side); + + /* compute control point */ + SW_FT_Vector_From_Polar(&ctrl, length, phi + rotate); + ctrl.x += arc[1].x; + ctrl.y += arc[1].y; + + /* compute end point */ + SW_FT_Vector_From_Polar(&end, stroker->radius, + angle_out + rotate); + end.x += arc[0].x; + end.y += arc[0].y; + + if (stroker->handle_wide_strokes) { + SW_FT_Vector start; + SW_FT_Angle alpha1; + + /* determine whether the border radius is greater than the + */ + /* radius of curvature of the original arc */ + start = border->points[border->num_points - 1]; + + alpha1 = SW_FT_Atan2(end.x - start.x, end.y - start.y); + + /* is the direction of the border arc opposite to */ + /* that of the original arc? */ + if (ft_pos_abs(SW_FT_Angle_Diff(alpha0, alpha1)) > + SW_FT_ANGLE_PI / 2) { + SW_FT_Angle beta, gamma; + SW_FT_Vector bvec, delta; + SW_FT_Fixed blen, sinA, sinB, alen; + + /* use the sine rule to find the intersection point */ + beta = + SW_FT_Atan2(arc[2].x - start.x, arc[2].y - start.y); + gamma = SW_FT_Atan2(arc[0].x - end.x, arc[0].y - end.y); + + bvec.x = end.x - start.x; + bvec.y = end.y - start.y; + + blen = SW_FT_Vector_Length(&bvec); + + sinA = ft_pos_abs(SW_FT_Sin(alpha1 - gamma)); + sinB = ft_pos_abs(SW_FT_Sin(beta - gamma)); + + alen = SW_FT_MulDiv(blen, sinA, sinB); + + SW_FT_Vector_From_Polar(&delta, alen, beta); + delta.x += start.x; + delta.y += start.y; + + /* circumnavigate the negative sector backwards */ + border->movable = FALSE; + error = ft_stroke_border_lineto(border, &delta, FALSE); + if (error) goto Exit; + error = ft_stroke_border_lineto(border, &end, FALSE); + if (error) goto Exit; + error = ft_stroke_border_conicto(border, &ctrl, &start); + if (error) goto Exit; + /* and then move to the endpoint */ + error = ft_stroke_border_lineto(border, &end, FALSE); + if (error) goto Exit; + + continue; + } + + /* else fall through */ + } + + /* simply add an arc */ + error = ft_stroke_border_conicto(border, &ctrl, &end); + if (error) goto Exit; } - - /* else fall through */ - } - - /* simply add an arc */ - error = ft_stroke_border_conicto( border, &ctrl, &end ); - if ( error ) - goto Exit; } - } - arc -= 2; + arc -= 2; - stroker->angle_in = angle_out; + stroker->angle_in = angle_out; } stroker->center = *to; - Exit: +Exit: return error; - } - +} - /* documentation is in ftstroke.h */ - - SW_FT_Error - SW_FT_Stroker_CubicTo( SW_FT_Stroker stroker, - SW_FT_Vector* control1, - SW_FT_Vector* control2, - SW_FT_Vector* to ) - { - SW_FT_Error error = 0; - SW_FT_Vector bez_stack[37]; - SW_FT_Vector* arc; - SW_FT_Vector* limit = bez_stack + 32; - SW_FT_Bool first_arc = TRUE; +/* documentation is in ftstroke.h */ +SW_FT_Error SW_FT_Stroker_CubicTo(SW_FT_Stroker stroker, SW_FT_Vector* control1, + SW_FT_Vector* control2, SW_FT_Vector* to) +{ + SW_FT_Error error = 0; + SW_FT_Vector bez_stack[37]; + SW_FT_Vector* arc; + SW_FT_Vector* limit = bez_stack + 32; + SW_FT_Bool first_arc = TRUE; /* if all control points are coincident, this is a no-op; */ /* avoid creating a spurious corner */ - if ( SW_FT_IS_SMALL( stroker->center.x - control1->x ) && - SW_FT_IS_SMALL( stroker->center.y - control1->y ) && - SW_FT_IS_SMALL( control1->x - control2->x ) && - SW_FT_IS_SMALL( control1->y - control2->y ) && - SW_FT_IS_SMALL( control2->x - to->x ) && - SW_FT_IS_SMALL( control2->y - to->y ) ) - { - stroker->center = *to; - goto Exit; + if (SW_FT_IS_SMALL(stroker->center.x - control1->x) && + SW_FT_IS_SMALL(stroker->center.y - control1->y) && + SW_FT_IS_SMALL(control1->x - control2->x) && + SW_FT_IS_SMALL(control1->y - control2->y) && + SW_FT_IS_SMALL(control2->x - to->x) && + SW_FT_IS_SMALL(control2->y - to->y)) { + stroker->center = *to; + goto Exit; } - arc = bez_stack; + arc = bez_stack; arc[0] = *to; arc[1] = *control2; arc[2] = *control1; arc[3] = stroker->center; - while ( arc >= bez_stack ) - { - SW_FT_Angle angle_in, angle_mid, angle_out; - - - /* initialize with current direction */ - angle_in = angle_out = angle_mid = stroker->angle_in; - - if ( arc < limit && - !ft_cubic_is_small_enough( arc, &angle_in, - &angle_mid, &angle_out ) ) - { - if ( stroker->first_point ) - stroker->angle_in = angle_in; + while (arc >= bez_stack) { + SW_FT_Angle angle_in, angle_mid, angle_out; - ft_cubic_split( arc ); - arc += 3; - continue; - } + /* initialize with current direction */ + angle_in = angle_out = angle_mid = stroker->angle_in; - if ( first_arc ) - { - first_arc = FALSE; + if (arc < limit && + !ft_cubic_is_small_enough(arc, &angle_in, &angle_mid, &angle_out)) { + if (stroker->first_point) stroker->angle_in = angle_in; - /* process corner if necessary */ - if ( stroker->first_point ) - error = ft_stroker_subpath_start( stroker, angle_in, 0 ); - else - { - stroker->angle_out = angle_in; - error = ft_stroker_process_corner( stroker, 0 ); + ft_cubic_split(arc); + arc += 3; + continue; } - } - else if ( ft_pos_abs( SW_FT_Angle_Diff( stroker->angle_in, angle_in ) ) > - SW_FT_SMALL_CUBIC_THRESHOLD / 4 ) - { - /* if the deviation from one arc to the next is too great, */ - /* add a round corner */ - stroker->center = arc[3]; - stroker->angle_out = angle_in; - stroker->line_join = SW_FT_STROKER_LINEJOIN_ROUND; - - error = ft_stroker_process_corner( stroker, 0 ); - - /* reinstate line join style */ - stroker->line_join = stroker->line_join_saved; - } - - if ( error ) - goto Exit; - - /* the arc's angle is small enough; we can add it directly to each */ - /* border */ - { - SW_FT_Vector ctrl1, ctrl2, end; - SW_FT_Angle theta1, phi1, theta2, phi2, rotate, alpha0 = 0; - SW_FT_Fixed length1, length2; - SW_FT_StrokeBorder border; - SW_FT_Int side; - - - theta1 = SW_FT_Angle_Diff( angle_in, angle_mid ) / 2; - theta2 = SW_FT_Angle_Diff( angle_mid, angle_out ) / 2; - phi1 = ft_angle_mean( angle_in, angle_mid ); - phi2 = ft_angle_mean( angle_mid, angle_out ); - length1 = SW_FT_DivFix( stroker->radius, SW_FT_Cos( theta1 ) ); - length2 = SW_FT_DivFix( stroker->radius, SW_FT_Cos( theta2 ) ); - - /* compute direction of original arc */ - if ( stroker->handle_wide_strokes ) - alpha0 = SW_FT_Atan2( arc[0].x - arc[3].x, arc[0].y - arc[3].y ); - - for ( border = stroker->borders, side = 0; - side <= 1; - side++, border++ ) - { - rotate = SW_FT_SIDE_TO_ROTATE( side ); - - /* compute control points */ - SW_FT_Vector_From_Polar( &ctrl1, length1, phi1 + rotate ); - ctrl1.x += arc[2].x; - ctrl1.y += arc[2].y; - SW_FT_Vector_From_Polar( &ctrl2, length2, phi2 + rotate ); - ctrl2.x += arc[1].x; - ctrl2.y += arc[1].y; + if (first_arc) { + first_arc = FALSE; - /* compute end point */ - SW_FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate ); - end.x += arc[0].x; - end.y += arc[0].y; - - if ( stroker->handle_wide_strokes ) - { - SW_FT_Vector start; - SW_FT_Angle alpha1; - - - /* determine whether the border radius is greater than the */ - /* radius of curvature of the original arc */ - start = border->points[border->num_points - 1]; - - alpha1 = SW_FT_Atan2( end.x - start.x, end.y - start.y ); - - /* is the direction of the border arc opposite to */ - /* that of the original arc? */ - if ( ft_pos_abs( SW_FT_Angle_Diff( alpha0, alpha1 ) ) > - SW_FT_ANGLE_PI / 2 ) - { - SW_FT_Angle beta, gamma; - SW_FT_Vector bvec, delta; - SW_FT_Fixed blen, sinA, sinB, alen; - - - /* use the sine rule to find the intersection point */ - beta = SW_FT_Atan2( arc[3].x - start.x, arc[3].y - start.y ); - gamma = SW_FT_Atan2( arc[0].x - end.x, arc[0].y - end.y ); - - bvec.x = end.x - start.x; - bvec.y = end.y - start.y; - - blen = SW_FT_Vector_Length( &bvec ); - - sinA = ft_pos_abs( SW_FT_Sin( alpha1 - gamma ) ); - sinB = ft_pos_abs( SW_FT_Sin( beta - gamma ) ); - - alen = SW_FT_MulDiv( blen, sinA, sinB ); - - SW_FT_Vector_From_Polar( &delta, alen, beta ); - delta.x += start.x; - delta.y += start.y; - - /* circumnavigate the negative sector backwards */ - border->movable = FALSE; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - error = ft_stroke_border_lineto( border, &end, FALSE ); - if ( error ) - goto Exit; - error = ft_stroke_border_cubicto( border, - &ctrl2, - &ctrl1, - &start ); - if ( error ) - goto Exit; - /* and then move to the endpoint */ - error = ft_stroke_border_lineto( border, &end, FALSE ); - if ( error ) - goto Exit; - - continue; + /* process corner if necessary */ + if (stroker->first_point) + error = ft_stroker_subpath_start(stroker, angle_in, 0); + else { + stroker->angle_out = angle_in; + error = ft_stroker_process_corner(stroker, 0); } + } else if (ft_pos_abs(SW_FT_Angle_Diff(stroker->angle_in, angle_in)) > + SW_FT_SMALL_CUBIC_THRESHOLD / 4) { + /* if the deviation from one arc to the next is too great, */ + /* add a round corner */ + stroker->center = arc[3]; + stroker->angle_out = angle_in; + stroker->line_join = SW_FT_STROKER_LINEJOIN_ROUND; + + error = ft_stroker_process_corner(stroker, 0); + + /* reinstate line join style */ + stroker->line_join = stroker->line_join_saved; + } - /* else fall through */ - } + if (error) goto Exit; - /* simply add an arc */ - error = ft_stroke_border_cubicto( border, &ctrl1, &ctrl2, &end ); - if ( error ) - goto Exit; + /* the arc's angle is small enough; we can add it directly to each */ + /* border */ + { + SW_FT_Vector ctrl1, ctrl2, end; + SW_FT_Angle theta1, phi1, theta2, phi2, rotate, alpha0 = 0; + SW_FT_Fixed length1, length2; + SW_FT_StrokeBorder border; + SW_FT_Int side; + + theta1 = SW_FT_Angle_Diff(angle_in, angle_mid) / 2; + theta2 = SW_FT_Angle_Diff(angle_mid, angle_out) / 2; + phi1 = ft_angle_mean(angle_in, angle_mid); + phi2 = ft_angle_mean(angle_mid, angle_out); + length1 = SW_FT_DivFix(stroker->radius, SW_FT_Cos(theta1)); + length2 = SW_FT_DivFix(stroker->radius, SW_FT_Cos(theta2)); + + /* compute direction of original arc */ + if (stroker->handle_wide_strokes) + alpha0 = SW_FT_Atan2(arc[0].x - arc[3].x, arc[0].y - arc[3].y); + + for (border = stroker->borders, side = 0; side <= 1; + side++, border++) { + rotate = SW_FT_SIDE_TO_ROTATE(side); + + /* compute control points */ + SW_FT_Vector_From_Polar(&ctrl1, length1, phi1 + rotate); + ctrl1.x += arc[2].x; + ctrl1.y += arc[2].y; + + SW_FT_Vector_From_Polar(&ctrl2, length2, phi2 + rotate); + ctrl2.x += arc[1].x; + ctrl2.y += arc[1].y; + + /* compute end point */ + SW_FT_Vector_From_Polar(&end, stroker->radius, + angle_out + rotate); + end.x += arc[0].x; + end.y += arc[0].y; + + if (stroker->handle_wide_strokes) { + SW_FT_Vector start; + SW_FT_Angle alpha1; + + /* determine whether the border radius is greater than the + */ + /* radius of curvature of the original arc */ + start = border->points[border->num_points - 1]; + + alpha1 = SW_FT_Atan2(end.x - start.x, end.y - start.y); + + /* is the direction of the border arc opposite to */ + /* that of the original arc? */ + if (ft_pos_abs(SW_FT_Angle_Diff(alpha0, alpha1)) > + SW_FT_ANGLE_PI / 2) { + SW_FT_Angle beta, gamma; + SW_FT_Vector bvec, delta; + SW_FT_Fixed blen, sinA, sinB, alen; + + /* use the sine rule to find the intersection point */ + beta = + SW_FT_Atan2(arc[3].x - start.x, arc[3].y - start.y); + gamma = SW_FT_Atan2(arc[0].x - end.x, arc[0].y - end.y); + + bvec.x = end.x - start.x; + bvec.y = end.y - start.y; + + blen = SW_FT_Vector_Length(&bvec); + + sinA = ft_pos_abs(SW_FT_Sin(alpha1 - gamma)); + sinB = ft_pos_abs(SW_FT_Sin(beta - gamma)); + + alen = SW_FT_MulDiv(blen, sinA, sinB); + + SW_FT_Vector_From_Polar(&delta, alen, beta); + delta.x += start.x; + delta.y += start.y; + + /* circumnavigate the negative sector backwards */ + border->movable = FALSE; + error = ft_stroke_border_lineto(border, &delta, FALSE); + if (error) goto Exit; + error = ft_stroke_border_lineto(border, &end, FALSE); + if (error) goto Exit; + error = ft_stroke_border_cubicto(border, &ctrl2, &ctrl1, + &start); + if (error) goto Exit; + /* and then move to the endpoint */ + error = ft_stroke_border_lineto(border, &end, FALSE); + if (error) goto Exit; + + continue; + } + + /* else fall through */ + } + + /* simply add an arc */ + error = ft_stroke_border_cubicto(border, &ctrl1, &ctrl2, &end); + if (error) goto Exit; + } } - } - arc -= 3; + arc -= 3; - stroker->angle_in = angle_out; + stroker->angle_in = angle_out; } stroker->center = *to; - Exit: +Exit: return error; - } +} +/* documentation is in ftstroke.h */ - /* documentation is in ftstroke.h */ - - SW_FT_Error - SW_FT_Stroker_BeginSubPath( SW_FT_Stroker stroker, - SW_FT_Vector* to, - SW_FT_Bool open ) - { +SW_FT_Error SW_FT_Stroker_BeginSubPath(SW_FT_Stroker stroker, SW_FT_Vector* to, + SW_FT_Bool open) +{ /* We cannot process the first point, because there is not enough */ /* information regarding its corner/cap. The latter will be processed */ /* in the `SW_FT_Stroker_EndSubPath' routine. */ /* */ - stroker->first_point = TRUE; - stroker->center = *to; + stroker->first_point = TRUE; + stroker->center = *to; stroker->subpath_open = open; /* Determine if we need to check whether the border radius is greater */ @@ -1819,9 +1524,9 @@ /* be created, because round & miter joins and round & square caps */ /* cover the negative sector created with wide strokes. */ stroker->handle_wide_strokes = - SW_FT_BOOL( stroker->line_join != SW_FT_STROKER_LINEJOIN_ROUND || - ( stroker->subpath_open && - stroker->line_cap == SW_FT_STROKER_LINECAP_BUTT ) ); + SW_FT_BOOL(stroker->line_join != SW_FT_STROKER_LINEJOIN_ROUND || + (stroker->subpath_open && + stroker->line_cap == SW_FT_STROKER_LINECAP_BUTT)); /* record the subpath start point for each border */ stroker->subpath_start = *to; @@ -1829,464 +1534,385 @@ stroker->angle_in = 0; return 0; - } +} +static SW_FT_Error ft_stroker_add_reverse_left(SW_FT_Stroker stroker, + SW_FT_Bool open) +{ + SW_FT_StrokeBorder right = stroker->borders + 0; + SW_FT_StrokeBorder left = stroker->borders + 1; + SW_FT_Int new_points; + SW_FT_Error error = 0; - static SW_FT_Error - ft_stroker_add_reverse_left( SW_FT_Stroker stroker, - SW_FT_Bool open ) - { - SW_FT_StrokeBorder right = stroker->borders + 0; - SW_FT_StrokeBorder left = stroker->borders + 1; - SW_FT_Int new_points; - SW_FT_Error error = 0; - - - assert( left->start >= 0 ); + assert(left->start >= 0); new_points = left->num_points - left->start; - if ( new_points > 0 ) - { - error = ft_stroke_border_grow( right, (SW_FT_UInt)new_points ); - if ( error ) - goto Exit; - - { - SW_FT_Vector* dst_point = right->points + right->num_points; - SW_FT_Byte* dst_tag = right->tags + right->num_points; - SW_FT_Vector* src_point = left->points + left->num_points - 1; - SW_FT_Byte* src_tag = left->tags + left->num_points - 1; - + if (new_points > 0) { + error = ft_stroke_border_grow(right, (SW_FT_UInt)new_points); + if (error) goto Exit; - while ( src_point >= left->points + left->start ) { - *dst_point = *src_point; - *dst_tag = *src_tag; - - if ( open ) - dst_tag[0] &= ~SW_FT_STROKE_TAG_BEGIN_END; - else - { - SW_FT_Byte ttag = - (SW_FT_Byte)( dst_tag[0] & SW_FT_STROKE_TAG_BEGIN_END ); - - - /* switch begin/end tags if necessary */ - if ( ttag == SW_FT_STROKE_TAG_BEGIN || - ttag == SW_FT_STROKE_TAG_END ) - dst_tag[0] ^= SW_FT_STROKE_TAG_BEGIN_END; - } - - src_point--; - src_tag--; - dst_point++; - dst_tag++; + SW_FT_Vector* dst_point = right->points + right->num_points; + SW_FT_Byte* dst_tag = right->tags + right->num_points; + SW_FT_Vector* src_point = left->points + left->num_points - 1; + SW_FT_Byte* src_tag = left->tags + left->num_points - 1; + + while (src_point >= left->points + left->start) { + *dst_point = *src_point; + *dst_tag = *src_tag; + + if (open) + dst_tag[0] &= ~SW_FT_STROKE_TAG_BEGIN_END; + else { + SW_FT_Byte ttag = + (SW_FT_Byte)(dst_tag[0] & SW_FT_STROKE_TAG_BEGIN_END); + + /* switch begin/end tags if necessary */ + if (ttag == SW_FT_STROKE_TAG_BEGIN || + ttag == SW_FT_STROKE_TAG_END) + dst_tag[0] ^= SW_FT_STROKE_TAG_BEGIN_END; + } + + src_point--; + src_tag--; + dst_point++; + dst_tag++; + } } - } - left->num_points = left->start; - right->num_points += new_points; + left->num_points = left->start; + right->num_points += new_points; - right->movable = FALSE; - left->movable = FALSE; + right->movable = FALSE; + left->movable = FALSE; } - Exit: +Exit: return error; - } - - - /* documentation is in ftstroke.h */ - - /* there's a lot of magic in this function! */ - SW_FT_Error - SW_FT_Stroker_EndSubPath( SW_FT_Stroker stroker ) - { - SW_FT_Error error = 0; - +} + +/* documentation is in ftstroke.h */ + +/* there's a lot of magic in this function! */ +SW_FT_Error SW_FT_Stroker_EndSubPath(SW_FT_Stroker stroker) +{ + SW_FT_Error error = 0; + + if (stroker->subpath_open) { + SW_FT_StrokeBorder right = stroker->borders; + + /* All right, this is an opened path, we need to add a cap between */ + /* right & left, add the reverse of left, then add a final cap */ + /* between left & right. */ + error = ft_stroker_cap(stroker, stroker->angle_in, 0); + if (error) goto Exit; + + /* add reversed points from `left' to `right' */ + error = ft_stroker_add_reverse_left(stroker, TRUE); + if (error) goto Exit; + + /* now add the final cap */ + stroker->center = stroker->subpath_start; + error = + ft_stroker_cap(stroker, stroker->subpath_angle + SW_FT_ANGLE_PI, 0); + if (error) goto Exit; + + /* Now end the right subpath accordingly. The left one is */ + /* rewind and doesn't need further processing. */ + ft_stroke_border_close(right, FALSE); + } else { + SW_FT_Angle turn; + SW_FT_Int inside_side; + + /* close the path if needed */ + if (stroker->center.x != stroker->subpath_start.x || + stroker->center.y != stroker->subpath_start.y) { + error = SW_FT_Stroker_LineTo(stroker, &stroker->subpath_start); + if (error) goto Exit; + } - if ( stroker->subpath_open ) - { - SW_FT_StrokeBorder right = stroker->borders; + /* process the corner */ + stroker->angle_out = stroker->subpath_angle; + turn = SW_FT_Angle_Diff(stroker->angle_in, stroker->angle_out); + /* no specific corner processing is required if the turn is 0 */ + if (turn != 0) { + /* when we turn to the right, the inside side is 0 */ + inside_side = 0; - /* All right, this is an opened path, we need to add a cap between */ - /* right & left, add the reverse of left, then add a final cap */ - /* between left & right. */ - error = ft_stroker_cap( stroker, stroker->angle_in, 0 ); - if ( error ) - goto Exit; + /* otherwise, the inside side is 1 */ + if (turn < 0) inside_side = 1; - /* add reversed points from `left' to `right' */ - error = ft_stroker_add_reverse_left( stroker, TRUE ); - if ( error ) - goto Exit; + error = ft_stroker_inside(stroker, inside_side, + stroker->subpath_line_length); + if (error) goto Exit; - /* now add the final cap */ - stroker->center = stroker->subpath_start; - error = ft_stroker_cap( stroker, - stroker->subpath_angle + SW_FT_ANGLE_PI, 0 ); - if ( error ) - goto Exit; + /* process the outside side */ + error = ft_stroker_outside(stroker, 1 - inside_side, + stroker->subpath_line_length); + if (error) goto Exit; + } - /* Now end the right subpath accordingly. The left one is */ - /* rewind and doesn't need further processing. */ - ft_stroke_border_close( right, FALSE ); - } - else - { - SW_FT_Angle turn; - SW_FT_Int inside_side; - - - /* close the path if needed */ - if ( stroker->center.x != stroker->subpath_start.x || - stroker->center.y != stroker->subpath_start.y ) - { - error = SW_FT_Stroker_LineTo( stroker, &stroker->subpath_start ); - if ( error ) - goto Exit; - } - - /* process the corner */ - stroker->angle_out = stroker->subpath_angle; - turn = SW_FT_Angle_Diff( stroker->angle_in, - stroker->angle_out ); - - /* no specific corner processing is required if the turn is 0 */ - if ( turn != 0 ) - { - /* when we turn to the right, the inside side is 0 */ - inside_side = 0; - - /* otherwise, the inside side is 1 */ - if ( turn < 0 ) - inside_side = 1; - - error = ft_stroker_inside( stroker, - inside_side, - stroker->subpath_line_length ); - if ( error ) - goto Exit; - - /* process the outside side */ - error = ft_stroker_outside( stroker, - 1 - inside_side, - stroker->subpath_line_length ); - if ( error ) - goto Exit; - } - - /* then end our two subpaths */ - ft_stroke_border_close( stroker->borders + 0, FALSE ); - ft_stroke_border_close( stroker->borders + 1, TRUE ); + /* then end our two subpaths */ + ft_stroke_border_close(stroker->borders + 0, FALSE); + ft_stroke_border_close(stroker->borders + 1, TRUE); } - Exit: +Exit: return error; - } - - - /* documentation is in ftstroke.h */ +} - SW_FT_Error - SW_FT_Stroker_GetBorderCounts( SW_FT_Stroker stroker, - SW_FT_StrokerBorder border, - SW_FT_UInt *anum_points, - SW_FT_UInt *anum_contours ) - { - SW_FT_UInt num_points = 0, num_contours = 0; - SW_FT_Error error; +/* documentation is in ftstroke.h */ +SW_FT_Error SW_FT_Stroker_GetBorderCounts(SW_FT_Stroker stroker, + SW_FT_StrokerBorder border, + SW_FT_UInt* anum_points, + SW_FT_UInt* anum_contours) +{ + SW_FT_UInt num_points = 0, num_contours = 0; + SW_FT_Error error; - if ( !stroker || border > 1 ) - { - error = -1;//SW_FT_THROW( Invalid_Argument ); - goto Exit; + if (!stroker || border > 1) { + error = -1; // SW_FT_THROW( Invalid_Argument ); + goto Exit; } - error = ft_stroke_border_get_counts( stroker->borders + border, - &num_points, &num_contours ); - Exit: - if ( anum_points ) - *anum_points = num_points; + error = ft_stroke_border_get_counts(stroker->borders + border, &num_points, + &num_contours); +Exit: + if (anum_points) *anum_points = num_points; - if ( anum_contours ) - *anum_contours = num_contours; + if (anum_contours) *anum_contours = num_contours; return error; - } - +} - /* documentation is in ftstroke.h */ +/* documentation is in ftstroke.h */ - SW_FT_Error - SW_FT_Stroker_GetCounts( SW_FT_Stroker stroker, - SW_FT_UInt *anum_points, - SW_FT_UInt *anum_contours ) - { - SW_FT_UInt count1, count2, num_points = 0; - SW_FT_UInt count3, count4, num_contours = 0; - SW_FT_Error error; +SW_FT_Error SW_FT_Stroker_GetCounts(SW_FT_Stroker stroker, + SW_FT_UInt* anum_points, + SW_FT_UInt* anum_contours) +{ + SW_FT_UInt count1, count2, num_points = 0; + SW_FT_UInt count3, count4, num_contours = 0; + SW_FT_Error error; + error = ft_stroke_border_get_counts(stroker->borders + 0, &count1, &count2); + if (error) goto Exit; - error = ft_stroke_border_get_counts( stroker->borders + 0, - &count1, &count2 ); - if ( error ) - goto Exit; + error = ft_stroke_border_get_counts(stroker->borders + 1, &count3, &count4); + if (error) goto Exit; - error = ft_stroke_border_get_counts( stroker->borders + 1, - &count3, &count4 ); - if ( error ) - goto Exit; - - num_points = count1 + count3; + num_points = count1 + count3; num_contours = count2 + count4; - Exit: - *anum_points = num_points; +Exit: + *anum_points = num_points; *anum_contours = num_contours; return error; - } - - - /* documentation is in ftstroke.h */ +} - void - SW_FT_Stroker_ExportBorder( SW_FT_Stroker stroker, - SW_FT_StrokerBorder border, - SW_FT_Outline* outline ) - { - if ( border == SW_FT_STROKER_BORDER_LEFT || - border == SW_FT_STROKER_BORDER_RIGHT ) - { - SW_FT_StrokeBorder sborder = & stroker->borders[border]; +/* documentation is in ftstroke.h */ +void SW_FT_Stroker_ExportBorder(SW_FT_Stroker stroker, + SW_FT_StrokerBorder border, + SW_FT_Outline* outline) +{ + if (border == SW_FT_STROKER_BORDER_LEFT || + border == SW_FT_STROKER_BORDER_RIGHT) { + SW_FT_StrokeBorder sborder = &stroker->borders[border]; - if ( sborder->valid ) - ft_stroke_border_export( sborder, outline ); + if (sborder->valid) ft_stroke_border_export(sborder, outline); } - } - - - /* documentation is in ftstroke.h */ +} - void - SW_FT_Stroker_Export( SW_FT_Stroker stroker, - SW_FT_Outline* outline ) - { - SW_FT_Stroker_ExportBorder( stroker, SW_FT_STROKER_BORDER_LEFT, outline ); - SW_FT_Stroker_ExportBorder( stroker, SW_FT_STROKER_BORDER_RIGHT, outline ); - } +/* documentation is in ftstroke.h */ +void SW_FT_Stroker_Export(SW_FT_Stroker stroker, SW_FT_Outline* outline) +{ + SW_FT_Stroker_ExportBorder(stroker, SW_FT_STROKER_BORDER_LEFT, outline); + SW_FT_Stroker_ExportBorder(stroker, SW_FT_STROKER_BORDER_RIGHT, outline); +} - /* documentation is in ftstroke.h */ +/* documentation is in ftstroke.h */ - /* - * The following is very similar to SW_FT_Outline_Decompose, except - * that we do support opened paths, and do not scale the outline. - */ - SW_FT_Error - SW_FT_Stroker_ParseOutline( SW_FT_Stroker stroker, - const SW_FT_Outline* outline, - SW_FT_Bool opened ) - { - SW_FT_Vector v_last; - SW_FT_Vector v_control; - SW_FT_Vector v_start; +/* + * The following is very similar to SW_FT_Outline_Decompose, except + * that we do support opened paths, and do not scale the outline. + */ +SW_FT_Error SW_FT_Stroker_ParseOutline(SW_FT_Stroker stroker, + const SW_FT_Outline* outline, + SW_FT_Bool opened) +{ + SW_FT_Vector v_last; + SW_FT_Vector v_control; + SW_FT_Vector v_start; - SW_FT_Vector* point; - SW_FT_Vector* limit; - char* tags; + SW_FT_Vector* point; + SW_FT_Vector* limit; + char* tags; - SW_FT_Error error; + SW_FT_Error error; - SW_FT_Int n; /* index of contour in outline */ - SW_FT_UInt first; /* index of first point in contour */ - SW_FT_Int tag; /* current point's state */ + SW_FT_Int n; /* index of contour in outline */ + SW_FT_UInt first; /* index of first point in contour */ + SW_FT_Int tag; /* current point's state */ + if (!outline || !stroker) return -1; // SW_FT_THROW( Invalid_Argument ); - if ( !outline || !stroker ) - return -1;//SW_FT_THROW( Invalid_Argument ); - - SW_FT_Stroker_Rewind( stroker ); + SW_FT_Stroker_Rewind(stroker); first = 0; - for ( n = 0; n < outline->n_contours; n++ ) - { - SW_FT_UInt last; /* index of last point in contour */ - + for (n = 0; n < outline->n_contours; n++) { + SW_FT_UInt last; /* index of last point in contour */ - last = outline->contours[n]; - limit = outline->points + last; + last = outline->contours[n]; + limit = outline->points + last; - /* skip empty points; we don't stroke these */ - if ( last <= first ) - { - first = last + 1; - continue; - } - - v_start = outline->points[first]; - v_last = outline->points[last]; - - v_control = v_start; - - point = outline->points + first; - tags = outline->tags + first; - tag = SW_FT_CURVE_TAG( tags[0] ); - - /* A contour cannot start with a cubic control point! */ - if ( tag == SW_FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; - - /* check first point to determine origin */ - if ( tag == SW_FT_CURVE_TAG_CONIC ) - { - /* First point is conic control. Yes, this happens. */ - if ( SW_FT_CURVE_TAG( outline->tags[last] ) == SW_FT_CURVE_TAG_ON ) - { - /* start at last point if it is on the curve */ - v_start = v_last; - limit--; - } - else - { - /* if both first and last points are conic, */ - /* start at their middle */ - v_start.x = ( v_start.x + v_last.x ) / 2; - v_start.y = ( v_start.y + v_last.y ) / 2; + /* skip empty points; we don't stroke these */ + if (last <= first) { + first = last + 1; + continue; } - point--; - tags--; - } - error = SW_FT_Stroker_BeginSubPath( stroker, &v_start, opened ); - if ( error ) - goto Exit; - - while ( point < limit ) - { - point++; - tags++; - - tag = SW_FT_CURVE_TAG( tags[0] ); - switch ( tag ) - { - case SW_FT_CURVE_TAG_ON: /* emit a single line_to */ - { - SW_FT_Vector vec; + v_start = outline->points[first]; + v_last = outline->points[last]; + + v_control = v_start; + + point = outline->points + first; + tags = outline->tags + first; + tag = SW_FT_CURVE_TAG(tags[0]); + + /* A contour cannot start with a cubic control point! */ + if (tag == SW_FT_CURVE_TAG_CUBIC) goto Invalid_Outline; + + /* check first point to determine origin */ + if (tag == SW_FT_CURVE_TAG_CONIC) { + /* First point is conic control. Yes, this happens. */ + if (SW_FT_CURVE_TAG(outline->tags[last]) == SW_FT_CURVE_TAG_ON) { + /* start at last point if it is on the curve */ + v_start = v_last; + limit--; + } else { + /* if both first and last points are conic, */ + /* start at their middle */ + v_start.x = (v_start.x + v_last.x) / 2; + v_start.y = (v_start.y + v_last.y) / 2; + } + point--; + tags--; + } + error = SW_FT_Stroker_BeginSubPath(stroker, &v_start, opened); + if (error) goto Exit; - vec.x = point->x; - vec.y = point->y; + while (point < limit) { + point++; + tags++; - error = SW_FT_Stroker_LineTo( stroker, &vec ); - if ( error ) - goto Exit; - continue; - } + tag = SW_FT_CURVE_TAG(tags[0]); + switch (tag) { + case SW_FT_CURVE_TAG_ON: /* emit a single line_to */ + { + SW_FT_Vector vec; - case SW_FT_CURVE_TAG_CONIC: /* consume conic arcs */ - v_control.x = point->x; - v_control.y = point->y; + vec.x = point->x; + vec.y = point->y; - Do_Conic: - if ( point < limit ) - { - SW_FT_Vector vec; - SW_FT_Vector v_middle; + error = SW_FT_Stroker_LineTo(stroker, &vec); + if (error) goto Exit; + continue; + } + case SW_FT_CURVE_TAG_CONIC: /* consume conic arcs */ + v_control.x = point->x; + v_control.y = point->y; - point++; - tags++; - tag = SW_FT_CURVE_TAG( tags[0] ); + Do_Conic: + if (point < limit) { + SW_FT_Vector vec; + SW_FT_Vector v_middle; - vec = point[0]; + point++; + tags++; + tag = SW_FT_CURVE_TAG(tags[0]); - if ( tag == SW_FT_CURVE_TAG_ON ) - { - error = SW_FT_Stroker_ConicTo( stroker, &v_control, &vec ); - if ( error ) - goto Exit; - continue; - } + vec = point[0]; - if ( tag != SW_FT_CURVE_TAG_CONIC ) - goto Invalid_Outline; + if (tag == SW_FT_CURVE_TAG_ON) { + error = + SW_FT_Stroker_ConicTo(stroker, &v_control, &vec); + if (error) goto Exit; + continue; + } - v_middle.x = ( v_control.x + vec.x ) / 2; - v_middle.y = ( v_control.y + vec.y ) / 2; + if (tag != SW_FT_CURVE_TAG_CONIC) goto Invalid_Outline; - error = SW_FT_Stroker_ConicTo( stroker, &v_control, &v_middle ); - if ( error ) - goto Exit; + v_middle.x = (v_control.x + vec.x) / 2; + v_middle.y = (v_control.y + vec.y) / 2; - v_control = vec; - goto Do_Conic; - } + error = + SW_FT_Stroker_ConicTo(stroker, &v_control, &v_middle); + if (error) goto Exit; - error = SW_FT_Stroker_ConicTo( stroker, &v_control, &v_start ); - goto Close; + v_control = vec; + goto Do_Conic; + } - default: /* SW_FT_CURVE_TAG_CUBIC */ - { - SW_FT_Vector vec1, vec2; + error = SW_FT_Stroker_ConicTo(stroker, &v_control, &v_start); + goto Close; + default: /* SW_FT_CURVE_TAG_CUBIC */ + { + SW_FT_Vector vec1, vec2; - if ( point + 1 > limit || - SW_FT_CURVE_TAG( tags[1] ) != SW_FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; + if (point + 1 > limit || + SW_FT_CURVE_TAG(tags[1]) != SW_FT_CURVE_TAG_CUBIC) + goto Invalid_Outline; - point += 2; - tags += 2; + point += 2; + tags += 2; - vec1 = point[-2]; - vec2 = point[-1]; + vec1 = point[-2]; + vec2 = point[-1]; - if ( point <= limit ) - { - SW_FT_Vector vec; + if (point <= limit) { + SW_FT_Vector vec; + vec = point[0]; - vec = point[0]; + error = SW_FT_Stroker_CubicTo(stroker, &vec1, &vec2, &vec); + if (error) goto Exit; + continue; + } - error = SW_FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec ); - if ( error ) - goto Exit; - continue; + error = SW_FT_Stroker_CubicTo(stroker, &vec1, &vec2, &v_start); + goto Close; + } } - - error = SW_FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start ); - goto Close; - } } - } Close: - if ( error ) - goto Exit; + if (error) goto Exit; - /* don't try to end the path if no segments have been generated */ - if ( !stroker->first_point ) - { - error = SW_FT_Stroker_EndSubPath( stroker ); - if ( error ) - goto Exit; - } + /* don't try to end the path if no segments have been generated */ + if (!stroker->first_point) { + error = SW_FT_Stroker_EndSubPath(stroker); + if (error) goto Exit; + } - first = last + 1; + first = last + 1; } return 0; - Exit: +Exit: return error; - Invalid_Outline: - return -2;//SW_FT_THROW( Invalid_Outline ); - } - +Invalid_Outline: + return -2; // SW_FT_THROW( Invalid_Outline ); +} /* END */ diff --git a/src/vector/vbezier.cpp b/src/vector/vbezier.cpp index c3874f4..3651bc7 100644 --- a/src/vector/vbezier.cpp +++ b/src/vector/vbezier.cpp @@ -1,22 +1,21 @@ #include "vbezier.h" -#include +#include V_BEGIN_NAMESPACE // Approximate sqrt(x*x + y*y) using the alpha max plus beta min algorithm. // This uses alpha = 1, beta = 3/8, which results in a maximum error of less // than 7% compared to the correct value. -static inline float -lineLength(float x1, float y1, float x2, float y2) +static inline float lineLength(float x1, float y1, float x2, float y2) { - float x = x2 - x1; - float y = y2 - y1; + float x = x2 - x1; + float y = y2 - y1; - x = x < 0 ? -x : x; - y = y < 0 ? -y : y; + x = x < 0 ? -x : x; + y = y < 0 ? -y : y; - return (x > y ? x + 0.375 * y : y + 0.375 * x); + return (x > y ? x + 0.375 * y : y + 0.375 * x); } VBezier VBezier::fromPoints(const VPointF &p1, const VPointF &p2, @@ -34,42 +33,39 @@ VBezier VBezier::fromPoints(const VPointF &p1, const VPointF &p2, return b; } -float -VBezier::length()const +float VBezier::length() const { - VBezier left, right; /* bez poly splits */ - float len = 0.0; /* arc length */ - float chord; /* chord length */ - float length; + VBezier left, right; /* bez poly splits */ + float len = 0.0; /* arc length */ + float chord; /* chord length */ + float length; - len = len + lineLength(x1, y1, x2, y2); - len = len + lineLength(x2, y2, x3, y3); - len = len + lineLength(x3, y3, x4, y4); + len = len + lineLength(x1, y1, x2, y2); + len = len + lineLength(x2, y2, x3, y3); + len = len + lineLength(x3, y3, x4, y4); - chord = lineLength(x1, y1, x4, y4); + chord = lineLength(x1, y1, x4, y4); - if (!vCompare(len, chord)) { - split(&left, &right); /* split in two */ - length = - left.length() + /* try left side */ - right.length(); /* try right side */ + if (!vCompare(len, chord)) { + split(&left, &right); /* split in two */ + length = left.length() + /* try left side */ + right.length(); /* try right side */ - return length; - } + return length; + } - return len; + return len; } VBezier VBezier::onInterval(float t0, float t1) const { - if (t0 == 0 && t1 == 1) - return *this; + if (t0 == 0 && t1 == 1) return *this; VBezier bezier = *this; VBezier result; bezier.parameterSplitLeft(t0, &result); - float trueT = (t1-t0)/(1-t0); + float trueT = (t1 - t0) / (1 - t0); bezier.parameterSplitLeft(trueT, &result); return result; @@ -77,11 +73,10 @@ VBezier VBezier::onInterval(float t0, float t1) const float VBezier::tAtLength(float l) const { - float len = length(); - float t = 1.0; + float len = length(); + float t = 1.0; const float error = 0.01; - if (l > len || vCompare(l, len)) - return t; + if (l > len || vCompare(l, len)) return t; t *= 0.5; @@ -91,8 +86,7 @@ float VBezier::tAtLength(float l) const VBezier left; right.parameterSplitLeft(t, &left); float lLen = left.length(); - if (fabs(lLen - l) < error) - break; + if (fabs(lLen - l) < error) break; if (lLen < l) { t += (lastBigger - t) * 0.5; @@ -104,15 +98,13 @@ float VBezier::tAtLength(float l) const return t; } -void -VBezier::splitAtLength(float len, VBezier *left, VBezier *right) +void VBezier::splitAtLength(float len, VBezier *left, VBezier *right) { - float t; + float t; - *right = *this; - t = right->tAtLength(len); - right->parameterSplitLeft(t, left); + *right = *this; + t = right->tAtLength(len); + right->parameterSplitLeft(t, left); } V_END_NAMESPACE - diff --git a/src/vector/vbezier.h b/src/vector/vbezier.h index dd3f4cf..ccb5733 100644 --- a/src/vector/vbezier.h +++ b/src/vector/vbezier.h @@ -5,29 +5,31 @@ V_BEGIN_NAMESPACE -class VBezier -{ +class VBezier { public: - VBezier(){} - VPointF pointAt(float t)const; - VBezier onInterval(float t0, float t1)const; - float length()const; - static void coefficients(float t, float &a, float &b, float &c, float &d); - static VBezier fromPoints(const VPointF &start, const VPointF &cp1, const VPointF &cp2, const VPointF &end); - inline void parameterSplitLeft(float t, VBezier *left); - inline void split(VBezier *firstHalf, VBezier *secondHalf) const; - float tAtLength(float len) const; - void splitAtLength(float len, VBezier *left, VBezier *right); - VPointF pt1() const { return VPointF(x1, y1); } - VPointF pt2() const { return VPointF(x2, y2); } - VPointF pt3() const { return VPointF(x3, y3); } - VPointF pt4() const { return VPointF(x4, y4); } + VBezier() {} + VPointF pointAt(float t) const; + VBezier onInterval(float t0, float t1) const; + float length() const; + static void coefficients(float t, float &a, float &b, float &c, float &d); + static VBezier fromPoints(const VPointF &start, const VPointF &cp1, + const VPointF &cp2, const VPointF &end); + inline void parameterSplitLeft(float t, VBezier *left); + inline void split(VBezier *firstHalf, VBezier *secondHalf) const; + float tAtLength(float len) const; + void splitAtLength(float len, VBezier *left, VBezier *right); + VPointF pt1() const { return VPointF(x1, y1); } + VPointF pt2() const { return VPointF(x2, y2); } + VPointF pt3() const { return VPointF(x3, y3); } + VPointF pt4() const { return VPointF(x4, y4); } + private: - VPointF derivative(float t)const; - float x1,y1,x2,y2,x3,y3,x4,y4; + VPointF derivative(float t) const; + float x1, y1, x2, y2, x3, y3, x4, y4; }; -inline void VBezier::coefficients(float t, float &a, float &b, float &c, float &d) +inline void VBezier::coefficients(float t, float &a, float &b, float &c, + float &d) { float m_t = 1. - t; b = m_t * m_t; @@ -45,20 +47,20 @@ inline VPointF VBezier::pointAt(float t) const float m_t = 1. - t; { - float a = x1*m_t + x2*t; - float b = x2*m_t + x3*t; - float c = x3*m_t + x4*t; - a = a*m_t + b*t; - b = b*m_t + c*t; - x = a*m_t + b*t; + float a = x1 * m_t + x2 * t; + float b = x2 * m_t + x3 * t; + float c = x3 * m_t + x4 * t; + a = a * m_t + b * t; + b = b * m_t + c * t; + x = a * m_t + b * t; } { - float a = y1*m_t + y2*t; - float b = y2*m_t + y3*t; - float c = y3*m_t + y4*t; - a = a*m_t + b*t; - b = b*m_t + c*t; - y = a*m_t + b*t; + float a = y1 * m_t + y2 * t; + float b = y2 * m_t + y3 * t; + float c = y3 * m_t + y4 * t; + a = a * m_t + b * t; + b = b * m_t + c * t; + y = a * m_t + b * t; } return VPointF(x, y); } @@ -68,20 +70,20 @@ inline void VBezier::parameterSplitLeft(float t, VBezier *left) left->x1 = x1; left->y1 = y1; - left->x2 = x1 + t * ( x2 - x1 ); - left->y2 = y1 + t * ( y2 - y1 ); + left->x2 = x1 + t * (x2 - x1); + left->y2 = y1 + t * (y2 - y1); - left->x3 = x2 + t * ( x3 - x2 ); // temporary holding spot - left->y3 = y2 + t * ( y3 - y2 ); // temporary holding spot + left->x3 = x2 + t * (x3 - x2); // temporary holding spot + left->y3 = y2 + t * (y3 - y2); // temporary holding spot - x3 = x3 + t * ( x4 - x3 ); - y3 = y3 + t * ( y4 - y3 ); + x3 = x3 + t * (x4 - x3); + y3 = y3 + t * (y4 - y3); - x2 = left->x3 + t * ( x3 - left->x3); - y2 = left->y3 + t * ( y3 - left->y3); + x2 = left->x3 + t * (x3 - left->x3); + y2 = left->y3 + t * (y3 - left->y3); - left->x3 = left->x2 + t * ( left->x3 - left->x2 ); - left->y3 = left->y2 + t * ( left->y3 - left->y2 ); + left->x3 = left->x2 + t * (left->x3 - left->x2); + left->y3 = left->y2 + t * (left->y3 - left->y2); left->x4 = x1 = left->x3 + t * (x2 - left->x3); left->y4 = y1 = left->y3 + t * (y2 - left->y3); @@ -89,25 +91,25 @@ inline void VBezier::parameterSplitLeft(float t, VBezier *left) inline void VBezier::split(VBezier *firstHalf, VBezier *secondHalf) const { - float c = (x2 + x3)*.5; - firstHalf->x2 = (x1 + x2)*.5; - secondHalf->x3 = (x3 + x4)*.5; + float c = (x2 + x3) * .5; + firstHalf->x2 = (x1 + x2) * .5; + secondHalf->x3 = (x3 + x4) * .5; firstHalf->x1 = x1; secondHalf->x4 = x4; - firstHalf->x3 = (firstHalf->x2 + c)*.5; - secondHalf->x2 = (secondHalf->x3 + c)*.5; - firstHalf->x4 = secondHalf->x1 = (firstHalf->x3 + secondHalf->x2)*.5; + firstHalf->x3 = (firstHalf->x2 + c) * .5; + secondHalf->x2 = (secondHalf->x3 + c) * .5; + firstHalf->x4 = secondHalf->x1 = (firstHalf->x3 + secondHalf->x2) * .5; - c = (y2 + y3)/2; - firstHalf->y2 = (y1 + y2)*.5; - secondHalf->y3 = (y3 + y4)*.5; + c = (y2 + y3) / 2; + firstHalf->y2 = (y1 + y2) * .5; + secondHalf->y3 = (y3 + y4) * .5; firstHalf->y1 = y1; secondHalf->y4 = y4; - firstHalf->y3 = (firstHalf->y2 + c)*.5; - secondHalf->y2 = (secondHalf->y3 + c)*.5; - firstHalf->y4 = secondHalf->y1 = (firstHalf->y3 + secondHalf->y2)*.5; + firstHalf->y3 = (firstHalf->y2 + c) * .5; + secondHalf->y2 = (secondHalf->y3 + c) * .5; + firstHalf->y4 = secondHalf->y1 = (firstHalf->y3 + secondHalf->y2) * .5; } V_END_NAMESPACE -#endif //VBEZIER_H +#endif // VBEZIER_H diff --git a/src/vector/vbitmap.cpp b/src/vector/vbitmap.cpp index f92c9ca..5e18fde 100644 --- a/src/vector/vbitmap.cpp +++ b/src/vector/vbitmap.cpp @@ -1,45 +1,50 @@ #include "vbitmap.h" +#include #include "vglobal.h" -#include V_BEGIN_NAMESPACE -struct VBitmapData -{ +struct VBitmapData { ~VBitmapData(); VBitmapData(); static VBitmapData *create(int width, int height, VBitmap::Format format); - RefCount ref; - int width; - int height; - int depth; - int stride; - int nBytes; - VBitmap::Format format; - uchar *data; - VBitmapCleanupFunction cleanupFunction; - void* cleanupInfo; - uint ownData : 1; - uint roData : 1; + RefCount ref; + int width; + int height; + int depth; + int stride; + int nBytes; + VBitmap::Format format; + uchar * data; + VBitmapCleanupFunction cleanupFunction; + void * cleanupInfo; + uint ownData : 1; + uint roData : 1; }; VBitmapData::~VBitmapData() { - if (cleanupFunction) - cleanupFunction(cleanupInfo); - if (data && ownData) - free(data); + if (cleanupFunction) cleanupFunction(cleanupInfo); + if (data && ownData) free(data); data = 0; } VBitmapData::VBitmapData() - : ref(0), width(0), height(0), depth(0), stride(0), - format(VBitmap::Format::ARGB32), data(nullptr), - cleanupFunction(0), cleanupInfo(0), ownData(true), roData(false) + : ref(0), + width(0), + height(0), + depth(0), + stride(0), + format(VBitmap::Format::ARGB32), + data(nullptr), + cleanupFunction(0), + cleanupInfo(0), + ownData(true), + roData(false) { } -VBitmapData * VBitmapData::create(int width, int height, VBitmap::Format format) +VBitmapData *VBitmapData::create(int width, int height, VBitmap::Format format) { if ((width <= 0) || (height <= 0) || format == VBitmap::Format::Invalid) return nullptr; @@ -56,7 +61,8 @@ VBitmapData * VBitmapData::create(int width, int height, VBitmap::Format format) break; } - const int stride = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 4) + const int stride = ((width * depth + 31) >> 5) + << 2; // bytes per scanline (must be multiple of 4) VBitmapData *d = new VBitmapData; @@ -65,8 +71,8 @@ VBitmapData * VBitmapData::create(int width, int height, VBitmap::Format format) d->depth = depth; d->format = format; d->stride = stride; - d->nBytes = d->stride*height; - d->data = (uchar *)malloc(d->nBytes); + d->nBytes = d->stride * height; + d->data = (uchar *)malloc(d->nBytes); if (!d->data) { delete d; @@ -84,8 +90,7 @@ inline void VBitmap::cleanUp(VBitmapData *d) void VBitmap::detach() { if (d) { - if (d->ref.isShared() || d->roData) - *this = copy(); + if (d->ref.isShared() || d->roData) *this = copy(); } } @@ -93,24 +98,18 @@ VBitmap::~VBitmap() { if (!d) return; - if (!d->ref.deref()) - cleanUp(d); + if (!d->ref.deref()) cleanUp(d); } -VBitmap::VBitmap() - : d(nullptr) -{ - -} +VBitmap::VBitmap() : d(nullptr) {} VBitmap::VBitmap(const VBitmap &other) { d = other.d; - if (d) - d->ref.ref(); + if (d) d->ref.ref(); } -VBitmap::VBitmap(VBitmap &&other): d(other.d) +VBitmap::VBitmap(VBitmap &&other) : d(other.d) { other.d = nullptr; } @@ -119,11 +118,9 @@ VBitmap &VBitmap::operator=(const VBitmap &other) { if (!d) { d = other.d; - if (d) - d->ref.ref(); + if (d) d->ref.ref(); } else { - if (!d->ref.deref()) - cleanUp(d); + if (!d->ref.deref()) cleanUp(d); other.d->ref.ref(); d = other.d; } @@ -133,18 +130,15 @@ VBitmap &VBitmap::operator=(const VBitmap &other) inline VBitmap &VBitmap::operator=(VBitmap &&other) { - if (d && !d->ref.deref()) - cleanUp(d); + if (d && !d->ref.deref()) cleanUp(d); d = other.d; return *this; } -VBitmap::VBitmap(int w, int h, VBitmap::Format format) -{ - -} -VBitmap::VBitmap(uchar *data, int w, int h, int bytesPerLine, VBitmap::Format format, - VBitmapCleanupFunction f, void *cleanupInfo) +VBitmap::VBitmap(int w, int h, VBitmap::Format format) {} +VBitmap::VBitmap(uchar *data, int w, int h, int bytesPerLine, + VBitmap::Format format, VBitmapCleanupFunction f, + void *cleanupInfo) { d = new VBitmapData; d->data = data; @@ -159,15 +153,13 @@ VBitmap::VBitmap(uchar *data, int w, int h, int bytesPerLine, VBitmap::Format fo d->ref.setOwned(); } -VBitmap VBitmap::copy(const VRect& r) const +VBitmap VBitmap::copy(const VRect &r) const { - if (!d) - return VBitmap(); + if (!d) return VBitmap(); if (r.isNull()) { VBitmap image(d->width, d->height, d->format); - if (image.isNull()) - return image; + if (image.isNull()) return image; if (image.d->nBytes != d->nBytes) { int bpl = vMin(stride(), image.stride()); @@ -185,12 +177,10 @@ VBitmap VBitmap::copy(const VRect& r) const int dx = 0; int dy = 0; - if (w <= 0 || h <= 0) - return VBitmap(); + if (w <= 0 || h <= 0) return VBitmap(); VBitmap image(w, h, d->format); - if (image.isNull()) - return image; + if (image.isNull()) return image; if (x < 0 || y < 0 || x + w > d->width || y + h > d->height) { // bitBlt will not cover entire image - clear it. @@ -204,9 +194,8 @@ VBitmap VBitmap::copy(const VRect& r) const y = 0; } } - //TODO implement properly. + // TODO implement properly. return image; - } int VBitmap::stride() const @@ -226,13 +215,11 @@ int VBitmap::height() const uchar *VBitmap::bits() { - if (!d) - return 0; + if (!d) return 0; detach(); // In case detach ran out of memory... - if (!d) - return 0; + if (!d) return 0; return d->data; } @@ -249,39 +236,33 @@ bool VBitmap::isNull() const uchar *VBitmap::scanLine(int i) { - if (!d) - return 0; + if (!d) return 0; detach(); // In case detach() ran out of memory - if (!d) - return 0; + if (!d) return 0; return d->data + i * d->stride; } const uchar *VBitmap::scanLine(int i) const { - if (!d) - return 0; + if (!d) return 0; - //assert(i >= 0 && i < height()); + // assert(i >= 0 && i < height()); return d->data + i * d->stride; } VBitmap::Format VBitmap::format() const { - if (!d) - return VBitmap::Format::Invalid; + if (!d) return VBitmap::Format::Invalid; return d->format; } - void VBitmap::fill(uint pixel) { - if (!d) - return; + if (!d) return; } V_END_NAMESPACE diff --git a/src/vector/vbitmap.h b/src/vector/vbitmap.h index ca3f2a1..a5223d9 100644 --- a/src/vector/vbitmap.h +++ b/src/vector/vbitmap.h @@ -7,16 +7,9 @@ V_BEGIN_NAMESPACE struct VBitmapData; typedef void (*VBitmapCleanupFunction)(void *); -class VBitmap -{ +class VBitmap { public: - enum class Format { - Invalid, - Alpha8, - ARGB32, - ARGB32_Premultiplied, - Last - }; + enum class Format { Invalid, Alpha8, ARGB32, ARGB32_Premultiplied, Last }; ~VBitmap(); VBitmap(); VBitmap(const VBitmap &other); @@ -29,23 +22,24 @@ public: VBitmapCleanupFunction f = nullptr, void *cleanupInfo = nullptr); VBitmap copy(const VRect &rect = VRect()) const; - void fill(uint pixel); - - int width() const; - int height() const; - uchar *bits(); - const uchar *bits() const; - uchar *scanLine(int); - const uchar *scanLine(int) const; - int stride() const; - bool isNull() const; + void fill(uint pixel); + + int width() const; + int height() const; + uchar * bits(); + const uchar * bits() const; + uchar * scanLine(int); + const uchar * scanLine(int) const; + int stride() const; + bool isNull() const; VBitmap::Format format() const; + private: - void detach(); - void cleanUp(VBitmapData *x); - VBitmapData *d; + void detach(); + void cleanUp(VBitmapData *x); + VBitmapData *d; }; V_END_NAMESPACE -#endif // VBITMAP_H +#endif // VBITMAP_H diff --git a/src/vector/vbrush.cpp b/src/vector/vbrush.cpp index 55b015d..def6797 100644 --- a/src/vector/vbrush.cpp +++ b/src/vector/vbrush.cpp @@ -1,10 +1,12 @@ -#include"vbrush.h" +#include "vbrush.h" V_BEGIN_NAMESPACE -VGradient::VGradient(VGradient::Type type):mType(type), mSpread(VGradient::Spread::Pad), mMode(VGradient::Mode::Absolute) +VGradient::VGradient(VGradient::Type type) + : mType(type), + mSpread(VGradient::Spread::Pad), + mMode(VGradient::Mode::Absolute) { - } void VGradient::setStops(const VGradientStops &stops) @@ -12,8 +14,8 @@ void VGradient::setStops(const VGradientStops &stops) mStops = stops; } -VLinearGradient::VLinearGradient(const VPointF &start, - const VPointF &stop):VGradient(VGradient::Type::Linear) +VLinearGradient::VLinearGradient(const VPointF &start, const VPointF &stop) + : VGradient(VGradient::Type::Linear) { linear.x1 = start.x(); linear.y1 = start.y(); @@ -21,8 +23,9 @@ VLinearGradient::VLinearGradient(const VPointF &start, linear.y1 = stop.y(); } -VLinearGradient::VLinearGradient(float xStart, float yStart, - float xStop, float yStop):VGradient(VGradient::Type::Linear) +VLinearGradient::VLinearGradient(float xStart, float yStart, float xStop, + float yStop) + : VGradient(VGradient::Type::Linear) { linear.x1 = xStart; linear.y1 = yStart; @@ -31,7 +34,8 @@ VLinearGradient::VLinearGradient(float xStart, float yStart, } VRadialGradient::VRadialGradient(const VPointF ¢er, float cradius, - const VPointF &focalPoint, float fradius):VGradient(VGradient::Type::Radial) + const VPointF &focalPoint, float fradius) + : VGradient(VGradient::Type::Radial) { radial.cx = center.x(); radial.cy = center.y(); @@ -41,8 +45,9 @@ VRadialGradient::VRadialGradient(const VPointF ¢er, float cradius, radial.fradius = fradius; } -VRadialGradient::VRadialGradient(float cx, float cy, float cradius, - float fx, float fy, float fradius):VGradient(VGradient::Type::Radial) +VRadialGradient::VRadialGradient(float cx, float cy, float cradius, float fx, + float fy, float fradius) + : VGradient(VGradient::Type::Radial) { radial.cx = cx; radial.cy = cy; @@ -52,20 +57,17 @@ VRadialGradient::VRadialGradient(float cx, float cy, float cradius, radial.fradius = fradius; } -VBrush::VBrush(const VColor &color):mType(VBrush::Type::Solid), - mColor(color) +VBrush::VBrush(const VColor &color) : mType(VBrush::Type::Solid), mColor(color) { - } -VBrush::VBrush(int r, int g, int b, int a):mType(VBrush::Type::Solid), - mColor(r, g, b, a) +VBrush::VBrush(int r, int g, int b, int a) + : mType(VBrush::Type::Solid), mColor(r, g, b, a) { - } -VBrush::VBrush(const VGradient *gradient):mType(VBrush::Type::NoBrush) +VBrush::VBrush(const VGradient *gradient) : mType(VBrush::Type::NoBrush) { if (!gradient) return; diff --git a/src/vector/vbrush.h b/src/vector/vbrush.h index 772019f..29711f9 100644 --- a/src/vector/vbrush.h +++ b/src/vector/vbrush.h @@ -1,40 +1,30 @@ #ifndef VBRUSH_H #define VBRUSH_H -#include"vglobal.h" -#include"vpoint.h" -#include"vmatrix.h" -#include +#include +#include "vglobal.h" +#include "vmatrix.h" +#include "vpoint.h" V_BEGIN_NAMESPACE -typedef std::pair VGradientStop; +typedef std::pair VGradientStop; typedef std::vector VGradientStops; -class VGradient -{ +class VGradient { public: - enum class Mode { - Absolute, - Relative - }; - enum class Spread { - Pad, - Repeat, - Reflect - }; - enum class Type { - Linear, - Radial - }; + enum class Mode { Absolute, Relative }; + enum class Spread { Pad, Repeat, Reflect }; + enum class Type { Linear, Radial }; VGradient(VGradient::Type type); void setStops(const VGradientStops &stops); - VGradient(){} + VGradient() {} + public: - static constexpr int colorTableSize = 1024; - VGradient::Type mType; - VGradient::Spread mSpread; - VGradient::Mode mMode; - VGradientStops mStops; + static constexpr int colorTableSize = 1024; + VGradient::Type mType; + VGradient::Spread mSpread; + VGradient::Mode mMode; + VGradientStops mStops; union { struct { float x1, y1, x2, y2; @@ -46,41 +36,35 @@ public: VMatrix mMatrix; }; -class VLinearGradient : public VGradient -{ +class VLinearGradient : public VGradient { public: VLinearGradient(const VPointF &start, const VPointF &stop); VLinearGradient(float xStart, float yStart, float xStop, float yStop); }; -class VRadialGradient : public VGradient -{ +class VRadialGradient : public VGradient { public: - VRadialGradient(const VPointF ¢er, float cradius, const VPointF &focalPoint, float fradius); - VRadialGradient(float cx, float cy, float cradius, float fx, float fy, float fradius); + VRadialGradient(const VPointF ¢er, float cradius, + const VPointF &focalPoint, float fradius); + VRadialGradient(float cx, float cy, float cradius, float fx, float fy, + float fradius); }; -class VBrush -{ +class VBrush { public: - enum class Type { - NoBrush, - Solid, - LinearGradient, - RadialGradient, - Texture - }; - VBrush():mType(Type::NoBrush){} + enum class Type { NoBrush, Solid, LinearGradient, RadialGradient, Texture }; + VBrush() : mType(Type::NoBrush) {} VBrush(const VColor &color); VBrush(const VGradient *gradient); VBrush(int r, int g, int b, int a); - inline VBrush::Type type() const{return mType;} + inline VBrush::Type type() const { return mType; } + public: - VBrush::Type mType; - VColor mColor; - const VGradient *mGradient; + VBrush::Type mType; + VColor mColor; + const VGradient *mGradient; }; V_END_NAMESPACE -#endif // VBRUSH_H +#endif // VBRUSH_H diff --git a/src/vector/vcompositionfunctions.cpp b/src/vector/vcompositionfunctions.cpp index 5122210..b55cf66 100644 --- a/src/vector/vcompositionfunctions.cpp +++ b/src/vector/vcompositionfunctions.cpp @@ -1,24 +1,22 @@ -#include"vdrawhelper.h" +#include "vdrawhelper.h" /* result = s dest = s * ca + d * cia */ -void comp_func_solid_Source(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha) +void comp_func_solid_Source(uint32_t *dest, int length, uint32_t color, + uint32_t const_alpha) { int ialpha, i; - if (const_alpha == 255) - { - memfill32(dest, color, length); - } - else - { - ialpha = 255 - const_alpha; - color = BYTE_MUL(color, const_alpha); - for (i = 0; i < length; ++i) - dest[i] = color + BYTE_MUL(dest[i], ialpha); - } + if (const_alpha == 255) { + memfill32(dest, color, length); + } else { + ialpha = 255 - const_alpha; + color = BYTE_MUL(color, const_alpha); + for (i = 0; i < length; ++i) + dest[i] = color + BYTE_MUL(dest[i], ialpha); + } } /* @@ -29,26 +27,26 @@ void comp_func_solid_Source(uint32_t *dest, int length, uint32_t color, uint32_t = s * ca + d * (1 - sa*ca) = s' + d ( 1 - s'a) */ -void comp_func_solid_SourceOver(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha) +void comp_func_solid_SourceOver(uint32_t *dest, int length, uint32_t color, + uint32_t const_alpha) { int ialpha, i; - if (const_alpha != 255) - color = BYTE_MUL(color, const_alpha); + if (const_alpha != 255) color = BYTE_MUL(color, const_alpha); ialpha = 255 - vAlpha(color); - for (i = 0; i < length; ++i) - dest[i] = color + BYTE_MUL(dest[i], ialpha); + for (i = 0; i < length; ++i) dest[i] = color + BYTE_MUL(dest[i], ialpha); } - -void comp_func_Source(uint32_t *dest, const uint32_t *src, int length, uint32_t const_alpha) +void comp_func_Source(uint32_t *dest, const uint32_t *src, int length, + uint32_t const_alpha) { if (const_alpha == 255) { memcpy(dest, src, size_t(length) * sizeof(uint)); } else { uint ialpha = 255 - const_alpha; for (int i = 0; i < length; ++i) { - dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha); + dest[i] = + INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha); } } } @@ -56,7 +54,8 @@ void comp_func_Source(uint32_t *dest, const uint32_t *src, int length, uint32_t /* s' = s * ca * d' = s' + d (1 - s'a) */ -void comp_func_SourceOver(uint32_t *dest, const uint32_t *src, int length, uint32_t const_alpha) +void comp_func_SourceOver(uint32_t *dest, const uint32_t *src, int length, + uint32_t const_alpha) { uint s, sia; @@ -66,8 +65,8 @@ void comp_func_SourceOver(uint32_t *dest, const uint32_t *src, int length, uint3 if (s >= 0xff000000) dest[i] = s; else if (s != 0) { - sia = vAlpha(~s); - dest[i] = s + BYTE_MUL(dest[i], sia); + sia = vAlpha(~s); + dest[i] = s + BYTE_MUL(dest[i], sia); } } } else { @@ -82,18 +81,10 @@ void comp_func_SourceOver(uint32_t *dest, const uint32_t *src, int length, uint3 } } - CompositionFunctionSolid COMP_functionForModeSolid_C[] = { - comp_func_solid_Source, - comp_func_solid_SourceOver -}; - -CompositionFunction COMP_functionForMode_C[] = { - comp_func_Source, - comp_func_SourceOver -}; + comp_func_solid_Source, comp_func_solid_SourceOver}; -void vInitBlendFunctions() -{ -} +CompositionFunction COMP_functionForMode_C[] = {comp_func_Source, + comp_func_SourceOver}; +void vInitBlendFunctions() {} diff --git a/src/vector/vcowptr.h b/src/vector/vcowptr.h index 8e94703..64aa554 100644 --- a/src/vector/vcowptr.h +++ b/src/vector/vcowptr.h @@ -1,7 +1,8 @@ #ifndef VCOWPTR_H #define VCOWPTR_H -#include +#include +#include "vglobal.h" template class vcow_ptr { @@ -11,42 +12,52 @@ class vcow_ptr { model() = default; template - explicit model(Args&&... args) : mValue(std::forward(args)...) {} + explicit model(Args&&... args) : mValue(std::forward(args)...) + { + } T mValue; }; model* mModel; + public: using element_type = T; - vcow_ptr() { + vcow_ptr() + { static model default_s; mModel = &default_s; ++mModel->mRef; } - ~vcow_ptr() { + ~vcow_ptr() + { if (mModel && (--mModel->mRef == 0)) delete mModel; } template - vcow_ptr(Args&&... args) - : mModel(new model(std::forward(args)...)) {} + vcow_ptr(Args&&... args) : mModel(new model(std::forward(args)...)) + { + } - vcow_ptr(const vcow_ptr& x) noexcept : mModel(x.mModel) { + vcow_ptr(const vcow_ptr& x) noexcept : mModel(x.mModel) + { assert(mModel); ++mModel->mRef; } - vcow_ptr(vcow_ptr&& x) noexcept : mModel(x.mModel) { + vcow_ptr(vcow_ptr&& x) noexcept : mModel(x.mModel) + { assert(mModel); x.mModel = nullptr; } - auto operator=(const vcow_ptr& x) noexcept -> vcow_ptr& { + auto operator=(const vcow_ptr& x) noexcept -> vcow_ptr& + { return *this = vcow_ptr(x); } - auto operator=(vcow_ptr&& x) noexcept -> vcow_ptr& { + auto operator=(vcow_ptr&& x) noexcept -> vcow_ptr& + { auto tmp = std::move(x); swap(*this, tmp); return *this; @@ -56,27 +67,31 @@ public: auto operator-> () const noexcept -> const element_type* { return &read(); } - bool unique() const noexcept { + bool unique() const noexcept + { assert(mModel); return mModel->mRef == 1; } - auto write() -> element_type& { + auto write() -> element_type& + { if (!unique()) *this = vcow_ptr(read()); return mModel->mValue; } - auto read() const noexcept -> const element_type& { + auto read() const noexcept -> const element_type& + { assert(mModel); return mModel->mValue; } - friend inline void swap(vcow_ptr& x, vcow_ptr& y) noexcept { + friend inline void swap(vcow_ptr& x, vcow_ptr& y) noexcept + { std::swap(x.mModel, y.mModel); } }; -#endif // VCOWPTR_H +#endif // VCOWPTR_H diff --git a/src/vector/vdasher.cpp b/src/vector/vdasher.cpp index f3d7f88..7fa920d 100644 --- a/src/vector/vdasher.cpp +++ b/src/vector/vdasher.cpp @@ -1,18 +1,24 @@ -#include"vdasher.h" -#include"vbezier.h" +#include "vdasher.h" +#include "vbezier.h" V_BEGIN_NAMESPACE -class VLine -{ +class VLine { public: - VLine():mX1(0),mY1(0),mX2(0),mY2(0){} - VLine(float x1, float y1, float x2, float y2):mX1(x1),mY1(y1),mX2(x2),mY2(y2){} - VLine(const VPointF &p1, const VPointF &p2):mX1(p1.x()),mY1(p1.y()),mX2(p2.x()),mY2(p2.y()){} - float length() const; - void splitAtLength(float length, VLine &left, VLine &right) const; - VPointF p1() const {return VPointF(mX1, mY1);} - VPointF p2() const {return VPointF(mX2, mY2);} + VLine() : mX1(0), mY1(0), mX2(0), mY2(0) {} + VLine(float x1, float y1, float x2, float y2) + : mX1(x1), mY1(y1), mX2(x2), mY2(y2) + { + } + VLine(const VPointF &p1, const VPointF &p2) + : mX1(p1.x()), mY1(p1.y()), mX2(p2.x()), mY2(p2.y()) + { + } + float length() const; + void splitAtLength(float length, VLine &left, VLine &right) const; + VPointF p1() const { return VPointF(mX1, mY1); } + VPointF p2() const { return VPointF(mX2, mY2); } + private: float mX1; float mY1; @@ -23,42 +29,39 @@ private: // approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm. // With alpha = 1, beta = 3/8, giving results with the largest error less // than 7% compared to the exact value. -float -VLine::length() const +float VLine::length() const { - float x = mX2 - mX1; - float y = mY2 - mY1; - x = x < 0 ? -x : x; - y = y < 0 ? -y : y; - return (x > y ? x + 0.375 * y : y + 0.375 * x); + float x = mX2 - mX1; + float y = mY2 - mY1; + x = x < 0 ? -x : x; + y = y < 0 ? -y : y; + return (x > y ? x + 0.375 * y : y + 0.375 * x); } -void -VLine::splitAtLength(float lengthAt, VLine &left, VLine &right) const +void VLine::splitAtLength(float lengthAt, VLine &left, VLine &right) const { - float len = length(); - double dx = ((mX2 - mX1)/len) *lengthAt; - double dy = ((mY2 - mY1)/len) *lengthAt; - - left.mX1 = mX1; - left.mY1 = mY1; - left.mX2 = left.mX1 + dx; - left.mY2 = left.mY1 + dy; - - right.mX1 = left.mX2; - right.mY1 = left.mY2; - right.mX2 = mX2; - right.mY2 = mY2; + float len = length(); + double dx = ((mX2 - mX1) / len) * lengthAt; + double dy = ((mY2 - mY1) / len) * lengthAt; + + left.mX1 = mX1; + left.mY1 = mY1; + left.mX2 = left.mX1 + dx; + left.mY2 = left.mY1 + dy; + + right.mX1 = left.mX2; + right.mY1 = left.mY2; + right.mX2 = mX2; + right.mY2 = mY2; } VDasher::VDasher(const float *dashArray, int size) { - if (!(size % 2)) - vCritical<<"invalid dashArray format"; + if (!(size % 2)) vCritical << "invalid dashArray format"; mDashArray = reinterpret_cast(dashArray); - mArraySize = size/2; - mDashOffset = dashArray[size-1]; + mArraySize = size / 2; + mDashOffset = dashArray[size - 1]; mCurrentDashIndex = 0; mCurrentDashLength = 0; mIsCurrentOperationGap = false; @@ -72,11 +75,11 @@ void VDasher::moveTo(const VPointF &p) if (!vCompare(mDashOffset, 0.0f)) { float totalLength = 0.0; - for (int i = 0; i < mArraySize ; i++) { + for (int i = 0; i < mArraySize; i++) { totalLength = mDashArray[i].length + mDashArray[i].gap; } float normalizeLen = fmod(mDashOffset, totalLength); - if (normalizeLen < 0.0 ) { + if (normalizeLen < 0.0) { normalizeLen = totalLength + normalizeLen; } // now the length is less than total length and +ve @@ -109,44 +112,44 @@ void VDasher::lineTo(const VPointF &p) VLine line(mCurPt, p); float length = line.length(); if (length < mCurrentDashLength) { - mCurrentDashLength -= length; - if (!mIsCurrentOperationGap) { - mDashedPath.moveTo(mCurPt); - mDashedPath.lineTo(p); - } + mCurrentDashLength -= length; + if (!mIsCurrentOperationGap) { + mDashedPath.moveTo(mCurPt); + mDashedPath.lineTo(p); + } } else { - while (length > mCurrentDashLength) { - length -= mCurrentDashLength; - line.splitAtLength(mCurrentDashLength, left, right); - if (!mIsCurrentOperationGap) { - mDashedPath.moveTo(left.p1()); - mDashedPath.lineTo(left.p2()); - mCurrentDashLength = mDashArray[mCurrentDashIndex].gap; - } else { - mCurrentDashIndex = (mCurrentDashIndex +1) % mArraySize ; - mCurrentDashLength = mDashArray[mCurrentDashIndex].length; - } - mIsCurrentOperationGap = !mIsCurrentOperationGap; - line = right; - mCurPt = line.p1(); - } - // remainder - mCurrentDashLength -= length; - if (!mIsCurrentOperationGap) { - mDashedPath.moveTo(line.p1()); - mDashedPath.lineTo(line.p2()); - } - if (mCurrentDashLength < 1.0) { - // move to next dash - if (!mIsCurrentOperationGap) { - mIsCurrentOperationGap = true; - mCurrentDashLength = mDashArray[mCurrentDashIndex].gap; - } else { - mIsCurrentOperationGap = false; - mCurrentDashIndex = (mCurrentDashIndex +1) % mArraySize; - mCurrentDashLength = mDashArray[mCurrentDashIndex].length; - } - } + while (length > mCurrentDashLength) { + length -= mCurrentDashLength; + line.splitAtLength(mCurrentDashLength, left, right); + if (!mIsCurrentOperationGap) { + mDashedPath.moveTo(left.p1()); + mDashedPath.lineTo(left.p2()); + mCurrentDashLength = mDashArray[mCurrentDashIndex].gap; + } else { + mCurrentDashIndex = (mCurrentDashIndex + 1) % mArraySize; + mCurrentDashLength = mDashArray[mCurrentDashIndex].length; + } + mIsCurrentOperationGap = !mIsCurrentOperationGap; + line = right; + mCurPt = line.p1(); + } + // remainder + mCurrentDashLength -= length; + if (!mIsCurrentOperationGap) { + mDashedPath.moveTo(line.p1()); + mDashedPath.lineTo(line.p2()); + } + if (mCurrentDashLength < 1.0) { + // move to next dash + if (!mIsCurrentOperationGap) { + mIsCurrentOperationGap = true; + mCurrentDashLength = mDashArray[mCurrentDashIndex].gap; + } else { + mIsCurrentOperationGap = false; + mCurrentDashIndex = (mCurrentDashIndex + 1) % mArraySize; + mCurrentDashLength = mDashArray[mCurrentDashIndex].length; + } + } } mCurPt = p; } @@ -154,87 +157,84 @@ void VDasher::lineTo(const VPointF &p) void VDasher::cubicTo(const VPointF &cp1, const VPointF &cp2, const VPointF &e) { VBezier left, right; - float bezLen = 0.0; + float bezLen = 0.0; VBezier b = VBezier::fromPoints(mCurPt, cp1, cp2, e); bezLen = b.length(); if (bezLen < mCurrentDashLength) { - mCurrentDashLength -= bezLen; - if (!mIsCurrentOperationGap) { - mDashedPath.moveTo(mCurPt); - mDashedPath.cubicTo(cp1, cp2, e); - } + mCurrentDashLength -= bezLen; + if (!mIsCurrentOperationGap) { + mDashedPath.moveTo(mCurPt); + mDashedPath.cubicTo(cp1, cp2, e); + } } else { - while (bezLen > mCurrentDashLength) { - bezLen -= mCurrentDashLength; - b.splitAtLength(mCurrentDashLength, &left, &right); - if (!mIsCurrentOperationGap) { - mDashedPath.moveTo(left.pt1()); - mDashedPath.cubicTo(left.pt2(), left.pt3(), left.pt4());; - mCurrentDashLength = mDashArray[mCurrentDashIndex].gap; - } else { - mCurrentDashIndex = (mCurrentDashIndex +1) % mArraySize ; - mCurrentDashLength = mDashArray[mCurrentDashIndex].length; - } - mIsCurrentOperationGap = !mIsCurrentOperationGap; - b = right; - mCurPt = b.pt1(); - } - // remainder - mCurrentDashLength -= bezLen; - if (!mIsCurrentOperationGap) { - mDashedPath.moveTo(b.pt1()); - mDashedPath.cubicTo(b.pt2(), b.pt3(), b.pt4()); - } - if (mCurrentDashLength < 1.0) { - // move to next dash - if (!mIsCurrentOperationGap) - { - mIsCurrentOperationGap = true; - mCurrentDashLength = mDashArray[mCurrentDashIndex].gap; - } - else - { - mIsCurrentOperationGap = false; - mCurrentDashIndex = (mCurrentDashIndex +1) % mArraySize; - mCurrentDashLength = mDashArray[mCurrentDashIndex].length; - } - } + while (bezLen > mCurrentDashLength) { + bezLen -= mCurrentDashLength; + b.splitAtLength(mCurrentDashLength, &left, &right); + if (!mIsCurrentOperationGap) { + mDashedPath.moveTo(left.pt1()); + mDashedPath.cubicTo(left.pt2(), left.pt3(), left.pt4()); + ; + mCurrentDashLength = mDashArray[mCurrentDashIndex].gap; + } else { + mCurrentDashIndex = (mCurrentDashIndex + 1) % mArraySize; + mCurrentDashLength = mDashArray[mCurrentDashIndex].length; + } + mIsCurrentOperationGap = !mIsCurrentOperationGap; + b = right; + mCurPt = b.pt1(); + } + // remainder + mCurrentDashLength -= bezLen; + if (!mIsCurrentOperationGap) { + mDashedPath.moveTo(b.pt1()); + mDashedPath.cubicTo(b.pt2(), b.pt3(), b.pt4()); + } + if (mCurrentDashLength < 1.0) { + // move to next dash + if (!mIsCurrentOperationGap) { + mIsCurrentOperationGap = true; + mCurrentDashLength = mDashArray[mCurrentDashIndex].gap; + } else { + mIsCurrentOperationGap = false; + mCurrentDashIndex = (mCurrentDashIndex + 1) % mArraySize; + mCurrentDashLength = mDashArray[mCurrentDashIndex].length; + } + } } mCurPt = e; } - VPath VDasher::dashed(const VPath &path) { if (path.isEmpty()) return VPath(); mDashedPath = VPath(); const std::vector &elms = path.elements(); - const std::vector &pts = path.points(); - const VPointF *ptPtr = pts.data(); + const std::vector & pts = path.points(); + const VPointF * ptPtr = pts.data(); for (auto i : elms) { switch (i) { - case VPath::Element::MoveTo: { - moveTo(*ptPtr++); - break; - } - case VPath::Element::LineTo: { - lineTo(*ptPtr++); - break; - } - case VPath::Element::CubicTo: { - cubicTo(*ptPtr, *(ptPtr + 1), *(ptPtr + 2)); - ptPtr += 3; - break; - } - case VPath::Element::Close: { - // The point is already joined to start point in VPath - // no need to do anything here. - break; - } - default: - break; + case VPath::Element::MoveTo: { + moveTo(*ptPtr++); + break; + } + case VPath::Element::LineTo: { + lineTo(*ptPtr++); + break; + } + case VPath::Element::CubicTo: { + cubicTo(*ptPtr, *(ptPtr + 1), *(ptPtr + 2)); + ptPtr += 3; + break; + } + case VPath::Element::Close: { + // The point is already joined to start point in VPath + // no need to do anything here. + break; + } + default: + break; } } return mDashedPath; diff --git a/src/vector/vdasher.h b/src/vector/vdasher.h index c200788..833e8c9 100644 --- a/src/vector/vdasher.h +++ b/src/vector/vdasher.h @@ -4,32 +4,33 @@ V_BEGIN_NAMESPACE -class VDasher -{ - public: +class VDasher { +public: VDasher(const float *dashArray, int size); VPath dashed(const VPath &path); - private: + +private: void moveTo(const VPointF &p); void lineTo(const VPointF &p); void cubicTo(const VPointF &cp1, const VPointF &cp2, const VPointF &e); void close(); + private: struct Dash { - float length; - float gap; + float length; + float gap; }; - const VDasher::Dash *mDashArray; - int mArraySize; - VPointF mStartPt; - VPointF mCurPt; - int mCurrentDashIndex; - float mCurrentDashLength; - bool mIsCurrentOperationGap; - float mDashOffset; - VPath mDashedPath; + const VDasher::Dash *mDashArray; + int mArraySize; + VPointF mStartPt; + VPointF mCurPt; + int mCurrentDashIndex; + float mCurrentDashLength; + bool mIsCurrentOperationGap; + float mDashOffset; + VPath mDashedPath; }; V_END_NAMESPACE -#endif // VDASHER_H +#endif // VDASHER_H diff --git a/src/vector/vdebug.cpp b/src/vector/vdebug.cpp index de0fe79..bc2fc3b 100644 --- a/src/vector/vdebug.cpp +++ b/src/vector/vdebug.cpp @@ -1,68 +1,70 @@ #include "vdebug.h" -#include +#include #include +#include #include +#include +#include +#include #include #include -#include -#include -#include -#include -namespace -{ +namespace { - /* Returns microseconds since epoch */ - uint64_t timestamp_now() - { - return std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); - } +/* Returns microseconds since epoch */ +uint64_t timestamp_now() +{ + return std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()) + .count(); +} - /* I want [2016-10-13 00:01:23.528514] */ - void format_timestamp(std::ostream & os, uint64_t timestamp) - { +/* I want [2016-10-13 00:01:23.528514] */ +void format_timestamp(std::ostream& os, uint64_t timestamp) +{ // The next 3 lines do not work on MSVC! // auto duration = std::chrono::microseconds(timestamp); // std::chrono::high_resolution_clock::time_point time_point(duration); - // std::time_t time_t = std::chrono::high_resolution_clock::to_time_t(time_point); + // std::time_t time_t = + // std::chrono::high_resolution_clock::to_time_t(time_point); std::time_t time_t = timestamp / 1000000; - auto gmtime = std::gmtime(&time_t); - char buffer[32]; + auto gmtime = std::gmtime(&time_t); + char buffer[32]; strftime(buffer, 32, "%Y-%m-%d %T.", gmtime); char microseconds[7]; sprintf(microseconds, "%06llu", timestamp % 1000000); os << '[' << buffer << microseconds << ']'; - } +} - std::thread::id this_thread_id() - { +std::thread::id this_thread_id() +{ static thread_local const std::thread::id id = std::this_thread::get_id(); return id; - } +} - template < typename T, typename Tuple > - struct TupleIndex; +template +struct TupleIndex; - template < typename T,typename ... Types > - struct TupleIndex < T, std::tuple < T, Types... > > - { +template +struct TupleIndex > { static constexpr const std::size_t value = 0; - }; +}; - template < typename T, typename U, typename ... Types > - struct TupleIndex < T, std::tuple < U, Types... > > - { - static constexpr const std::size_t value = 1 + TupleIndex < T, std::tuple < Types... > >::value; - }; +template +struct TupleIndex > { + static constexpr const std::size_t value = + 1 + TupleIndex >::value; +}; -} // anonymous namespace +} // anonymous namespace - typedef std::tuple < char, uint32_t, uint64_t, int32_t, int64_t, double, VDebug::string_literal_t, char * > SupportedTypes; +typedef std::tuple + SupportedTypes; - char const * to_string(LogLevel loglevel) - { - switch (loglevel) - { +char const* to_string(LogLevel loglevel) +{ + switch (loglevel) { case LogLevel::OFF: return "OFF"; case LogLevel::INFO: @@ -73,206 +75,244 @@ namespace return "CRIT"; } return "XXXX"; - } +} - template < typename Arg > - void VDebug::encode(Arg arg) - { +template +void VDebug::encode(Arg arg) +{ *reinterpret_cast(buffer()) = arg; m_bytes_used += sizeof(Arg); - } +} - template < typename Arg > - void VDebug::encode(Arg arg, uint8_t type_id) - { +template +void VDebug::encode(Arg arg, uint8_t type_id) +{ resize_buffer_if_needed(sizeof(Arg) + sizeof(uint8_t)); - encode < uint8_t >(type_id); - encode < Arg >(arg); - } + encode(type_id); + encode(arg); +} - VDebug::VDebug(LogLevel level, char const * file, char const * function, uint32_t line) - : m_bytes_used(0) - , m_buffer_size(sizeof(m_stack_buffer)) - { - encode < uint64_t >(timestamp_now()); - encode < std::thread::id >(this_thread_id()); - encode < string_literal_t >(string_literal_t(file)); - encode < string_literal_t >(string_literal_t(function)); - encode < uint32_t >(line); - encode < LogLevel >(level); +VDebug::VDebug(LogLevel level, char const* file, char const* function, + uint32_t line) + : m_bytes_used(0), m_buffer_size(sizeof(m_stack_buffer)) +{ + encode(timestamp_now()); + encode(this_thread_id()); + encode(string_literal_t(file)); + encode(string_literal_t(function)); + encode(line); + encode(level); if (level == LogLevel::INFO) { m_logAll = true; - }else { + } else { m_logAll = true; } - } +} - VDebug::~VDebug() = default; +VDebug::~VDebug() = default; - void VDebug::stringify(std::ostream & os) - { - char * b = !m_heap_buffer ? m_stack_buffer : m_heap_buffer.get(); - char const * const end = b + m_bytes_used; - uint64_t timestamp = *reinterpret_cast < uint64_t * >(b); b += sizeof(uint64_t); - std::thread::id threadid = *reinterpret_cast < std::thread::id * >(b); b += sizeof(std::thread::id); - string_literal_t file = *reinterpret_cast < string_literal_t * >(b); b += sizeof(string_literal_t); - string_literal_t function = *reinterpret_cast < string_literal_t * >(b); b += sizeof(string_literal_t); - uint32_t line = *reinterpret_cast < uint32_t * >(b); b += sizeof(uint32_t); - LogLevel loglevel = *reinterpret_cast < LogLevel * >(b); b += sizeof(LogLevel); +void VDebug::stringify(std::ostream& os) +{ + char* b = !m_heap_buffer ? m_stack_buffer : m_heap_buffer.get(); + char const* const end = b + m_bytes_used; + uint64_t timestamp = *reinterpret_cast(b); + b += sizeof(uint64_t); + std::thread::id threadid = *reinterpret_cast(b); + b += sizeof(std::thread::id); + string_literal_t file = *reinterpret_cast(b); + b += sizeof(string_literal_t); + string_literal_t function = *reinterpret_cast(b); + b += sizeof(string_literal_t); + uint32_t line = *reinterpret_cast(b); + b += sizeof(uint32_t); + LogLevel loglevel = *reinterpret_cast(b); + b += sizeof(LogLevel); if (m_logAll) { - format_timestamp(os, timestamp); - - os << '[' << to_string(loglevel) << ']' - << '[' << threadid << ']' - << '[' << file.m_s << ':' << function.m_s << ':' << line << "] "; + format_timestamp(os, timestamp); + os << '[' << to_string(loglevel) << ']' << '[' << threadid << ']' << '[' + << file.m_s << ':' << function.m_s << ':' << line << "] "; } stringify(os, b, end); os << std::endl; - if (loglevel >= LogLevel::CRIT) - os.flush(); - } + if (loglevel >= LogLevel::CRIT) os.flush(); +} - template < typename Arg > - char * decode(std::ostream & os, char * b, Arg * dummy) - { - Arg arg = *reinterpret_cast < Arg * >(b); +template +char* decode(std::ostream& os, char* b, Arg* dummy) +{ + Arg arg = *reinterpret_cast(b); os << arg; return b + sizeof(Arg); - } +} - template <> - char * decode(std::ostream & os, char * b, VDebug::string_literal_t * dummy) - { - VDebug::string_literal_t s = *reinterpret_cast < VDebug::string_literal_t * >(b); +template <> +char* decode(std::ostream& os, char* b, VDebug::string_literal_t* dummy) +{ + VDebug::string_literal_t s = + *reinterpret_cast(b); os << s.m_s; return b + sizeof(VDebug::string_literal_t); - } +} - template <> - char * decode(std::ostream & os, char * b, char ** dummy) - { - while (*b != '\0') - { +template <> +char* decode(std::ostream& os, char* b, char** dummy) +{ + while (*b != '\0') { os << *b; ++b; } return ++b; - } +} - void VDebug::stringify(std::ostream & os, char * start, char const * const end) - { - if (start == end) - return; +void VDebug::stringify(std::ostream& os, char* start, char const* const end) +{ + if (start == end) return; - int type_id = static_cast < int >(*start); start++; + int type_id = static_cast(*start); + start++; - switch (type_id) - { + switch (type_id) { case 0: - stringify(os, decode(os, start, static_cast::type*>(nullptr)), end); + stringify( + os, + decode(os, start, + static_cast::type*>( + nullptr)), + end); return; case 1: - stringify(os, decode(os, start, static_cast::type*>(nullptr)), end); + stringify( + os, + decode(os, start, + static_cast::type*>( + nullptr)), + end); return; case 2: - stringify(os, decode(os, start, static_cast::type*>(nullptr)), end); + stringify( + os, + decode(os, start, + static_cast::type*>( + nullptr)), + end); return; case 3: - stringify(os, decode(os, start, static_cast::type*>(nullptr)), end); + stringify( + os, + decode(os, start, + static_cast::type*>( + nullptr)), + end); return; case 4: - stringify(os, decode(os, start, static_cast::type*>(nullptr)), end); + stringify( + os, + decode(os, start, + static_cast::type*>( + nullptr)), + end); return; case 5: - stringify(os, decode(os, start, static_cast::type*>(nullptr)), end); + stringify( + os, + decode(os, start, + static_cast::type*>( + nullptr)), + end); return; case 6: - stringify(os, decode(os, start, static_cast::type*>(nullptr)), end); + stringify( + os, + decode(os, start, + static_cast::type*>( + nullptr)), + end); return; case 7: - stringify(os, decode(os, start, static_cast::type*>(nullptr)), end); + stringify( + os, + decode(os, start, + static_cast::type*>( + nullptr)), + end); return; } - } +} - char * VDebug::buffer() - { - return !m_heap_buffer ? &m_stack_buffer[m_bytes_used] : &(m_heap_buffer.get())[m_bytes_used]; - } +char* VDebug::buffer() +{ + return !m_heap_buffer ? &m_stack_buffer[m_bytes_used] + : &(m_heap_buffer.get())[m_bytes_used]; +} - void VDebug::resize_buffer_if_needed(size_t additional_bytes) - { +void VDebug::resize_buffer_if_needed(size_t additional_bytes) +{ size_t const required_size = m_bytes_used + additional_bytes; - if (required_size <= m_buffer_size) - return; + if (required_size <= m_buffer_size) return; - if (!m_heap_buffer) - { + if (!m_heap_buffer) { m_buffer_size = std::max(static_cast(512), required_size); m_heap_buffer.reset(new char[m_buffer_size]); memcpy(m_heap_buffer.get(), m_stack_buffer, m_bytes_used); return; - } - else - { - m_buffer_size = std::max(static_cast(2 * m_buffer_size), required_size); - std::unique_ptr < char [] > new_heap_buffer(new char[m_buffer_size]); + } else { + m_buffer_size = + std::max(static_cast(2 * m_buffer_size), required_size); + std::unique_ptr new_heap_buffer(new char[m_buffer_size]); memcpy(new_heap_buffer.get(), m_heap_buffer.get(), m_bytes_used); m_heap_buffer.swap(new_heap_buffer); } - } +} - void VDebug::encode(char const * arg) - { - if (arg != nullptr) - encode_c_string(arg, strlen(arg)); - } +void VDebug::encode(char const* arg) +{ + if (arg != nullptr) encode_c_string(arg, strlen(arg)); +} - void VDebug::encode(char * arg) - { - if (arg != nullptr) - encode_c_string(arg, strlen(arg)); - } +void VDebug::encode(char* arg) +{ + if (arg != nullptr) encode_c_string(arg, strlen(arg)); +} - void VDebug::encode_c_string(char const * arg, size_t length) - { - if (length == 0) - return; +void VDebug::encode_c_string(char const* arg, size_t length) +{ + if (length == 0) return; resize_buffer_if_needed(1 + length + 1); - char * b = buffer(); - auto type_id = TupleIndex < char *, SupportedTypes >::value; + char* b = buffer(); + auto type_id = TupleIndex::value; *reinterpret_cast(b++) = static_cast(type_id); memcpy(b, arg, length + 1); m_bytes_used += 1 + length + 1; - } +} - void VDebug::encode(string_literal_t arg) - { - encode < string_literal_t >(arg, TupleIndex < string_literal_t, SupportedTypes >::value); - } +void VDebug::encode(string_literal_t arg) +{ + encode( + arg, TupleIndex::value); +} - VDebug& VDebug::operator<<(std::string const & arg) - { +VDebug& VDebug::operator<<(std::string const& arg) +{ encode_c_string(arg.c_str(), arg.length()); return *this; - } +} - VDebug& VDebug::operator<<(int32_t arg) - { - encode < int32_t >(arg, TupleIndex < int32_t, SupportedTypes >::value); +VDebug& VDebug::operator<<(int32_t arg) +{ + encode(arg, TupleIndex::value); return *this; - } +} - VDebug& VDebug::operator<<(uint32_t arg) - { - encode < uint32_t >(arg, TupleIndex < uint32_t, SupportedTypes >::value); +VDebug& VDebug::operator<<(uint32_t arg) +{ + encode(arg, TupleIndex::value); return *this; - } +} // VDebug& VDebug::operator<<(int64_t arg) // { @@ -285,297 +325,281 @@ namespace // encode < uint64_t >(arg, TupleIndex < uint64_t, SupportedTypes >::value); // return *this; // } - VDebug& VDebug::operator<<(unsigned long arg) - { - encode < uint64_t >(arg, TupleIndex < uint64_t, SupportedTypes >::value); - return *this; - } +VDebug& VDebug::operator<<(unsigned long arg) +{ + encode(arg, TupleIndex::value); + return *this; +} - VDebug& VDebug::operator<<(long arg) - { - encode < int64_t >(arg, TupleIndex < int64_t, SupportedTypes >::value); - return *this; - } +VDebug& VDebug::operator<<(long arg) +{ + encode(arg, TupleIndex::value); + return *this; +} - VDebug& VDebug::operator<<(double arg) - { - encode < double >(arg, TupleIndex < double, SupportedTypes >::value); +VDebug& VDebug::operator<<(double arg) +{ + encode(arg, TupleIndex::value); return *this; - } +} - VDebug& VDebug::operator<<(char arg) - { - encode < char >(arg, TupleIndex < char, SupportedTypes >::value); +VDebug& VDebug::operator<<(char arg) +{ + encode(arg, TupleIndex::value); return *this; - } +} - struct BufferBase - { +struct BufferBase { virtual ~BufferBase() = default; - virtual void push(VDebug && logline) = 0; - virtual bool try_pop(VDebug & logline) = 0; - }; + virtual void push(VDebug&& logline) = 0; + virtual bool try_pop(VDebug& logline) = 0; +}; - struct SpinLock - { - SpinLock(std::atomic_flag & flag) : m_flag(flag) +struct SpinLock { + SpinLock(std::atomic_flag& flag) : m_flag(flag) { - while (m_flag.test_and_set(std::memory_order_acquire)); + while (m_flag.test_and_set(std::memory_order_acquire)) + ; } - ~SpinLock() - { - m_flag.clear(std::memory_order_release); - } + ~SpinLock() { m_flag.clear(std::memory_order_release); } - private: - std::atomic_flag & m_flag; - }; +private: + std::atomic_flag& m_flag; +}; - /* Multi Producer Single Consumer Ring Buffer */ - class RingBuffer : public BufferBase - { - public: - struct alignas(64) Item - { +/* Multi Producer Single Consumer Ring Buffer */ +class RingBuffer : public BufferBase { +public: + struct alignas(64) Item { Item() - : flag() - , written(0) - , logline(LogLevel::INFO, nullptr, nullptr, 0) + : flag(), written(0), logline(LogLevel::INFO, nullptr, nullptr, 0) { } std::atomic_flag flag; - char written; - char padding[256 - sizeof(std::atomic_flag) - sizeof(char) - sizeof(VDebug)]; - VDebug logline; - }; + char written; + char padding[256 - sizeof(std::atomic_flag) - sizeof(char) - + sizeof(VDebug)]; + VDebug logline; + }; - RingBuffer(size_t const size) - : m_size(size) - , m_ring(static_cast(std::malloc(size * sizeof(Item)))) - , m_write_index(0) - , m_read_index(0) - { - for (size_t i = 0; i < m_size; ++i) - { + RingBuffer(size_t const size) + : m_size(size), + m_ring(static_cast(std::malloc(size * sizeof(Item)))), + m_write_index(0), + m_read_index(0) + { + for (size_t i = 0; i < m_size; ++i) { new (&m_ring[i]) Item(); - } - static_assert(sizeof(Item) == 256, "Unexpected size != 256"); } + static_assert(sizeof(Item) == 256, "Unexpected size != 256"); + } - ~RingBuffer() - { - for (size_t i = 0; i < m_size; ++i) - { + ~RingBuffer() + { + for (size_t i = 0; i < m_size; ++i) { m_ring[i].~Item(); - } - std::free(m_ring); } + std::free(m_ring); + } - void push(VDebug && logline) override - { - unsigned int write_index = m_write_index.fetch_add(1, std::memory_order_relaxed) % m_size; - Item & item = m_ring[write_index]; - SpinLock spinlock(item.flag); + void push(VDebug&& logline) override + { + unsigned int write_index = + m_write_index.fetch_add(1, std::memory_order_relaxed) % m_size; + Item& item = m_ring[write_index]; + SpinLock spinlock(item.flag); item.logline = std::move(logline); item.written = 1; - } + } - bool try_pop(VDebug & logline) override - { - Item & item = m_ring[m_read_index % m_size]; - SpinLock spinlock(item.flag); - if (item.written == 1) - { + bool try_pop(VDebug& logline) override + { + Item& item = m_ring[m_read_index % m_size]; + SpinLock spinlock(item.flag); + if (item.written == 1) { logline = std::move(item.logline); item.written = 0; - ++m_read_index; + ++m_read_index; return true; - } - return false; } + return false; + } - RingBuffer(RingBuffer const &) = delete; - RingBuffer& operator=(RingBuffer const &) = delete; - - private: - size_t const m_size; - Item * m_ring; - std::atomic < unsigned int > m_write_index; - char pad[64]; - unsigned int m_read_index; - }; + RingBuffer(RingBuffer const&) = delete; + RingBuffer& operator=(RingBuffer const&) = delete; +private: + size_t const m_size; + Item* m_ring; + std::atomic m_write_index; + char pad[64]; + unsigned int m_read_index; +}; - class Buffer - { - public: - struct Item - { - Item(VDebug && logline) : logline(std::move(logline)) {} - char padding[256 - sizeof(VDebug)]; +class Buffer { +public: + struct Item { + Item(VDebug&& logline) : logline(std::move(logline)) {} + char padding[256 - sizeof(VDebug)]; VDebug logline; - }; + }; - static constexpr const size_t size = 32768; // 8MB. Helps reduce memory fragmentation + static constexpr const size_t size = + 32768; // 8MB. Helps reduce memory fragmentation - Buffer() : m_buffer(static_cast(std::malloc(size * sizeof(Item)))) - { - for (size_t i = 0; i <= size; ++i) - { + Buffer() : m_buffer(static_cast(std::malloc(size * sizeof(Item)))) + { + for (size_t i = 0; i <= size; ++i) { m_write_state[i].store(0, std::memory_order_relaxed); - } - static_assert(sizeof(Item) == 256, "Unexpected size != 256"); } + static_assert(sizeof(Item) == 256, "Unexpected size != 256"); + } - ~Buffer() - { + ~Buffer() + { unsigned int write_count = m_write_state[size].load(); - for (size_t i = 0; i < write_count; ++i) - { + for (size_t i = 0; i < write_count; ++i) { m_buffer[i].~Item(); - } - std::free(m_buffer); } + std::free(m_buffer); + } // Returns true if we need to switch to next buffer - bool push(VDebug && logline, unsigned int const write_index) - { + bool push(VDebug&& logline, unsigned int const write_index) + { new (&m_buffer[write_index]) Item(std::move(logline)); m_write_state[write_index].store(1, std::memory_order_release); - return m_write_state[size].fetch_add(1, std::memory_order_acquire) + 1 == size; - } + return m_write_state[size].fetch_add(1, std::memory_order_acquire) + + 1 == + size; + } - bool try_pop(VDebug & logline, unsigned int const read_index) - { - if (m_write_state[read_index].load(std::memory_order_acquire)) - { - Item & item = m_buffer[read_index]; - logline = std::move(item.logline); - return true; + bool try_pop(VDebug& logline, unsigned int const read_index) + { + if (m_write_state[read_index].load(std::memory_order_acquire)) { + Item& item = m_buffer[read_index]; + logline = std::move(item.logline); + return true; } return false; - } + } - Buffer(Buffer const &) = delete; - Buffer& operator=(Buffer const &) = delete; + Buffer(Buffer const&) = delete; + Buffer& operator=(Buffer const&) = delete; - private: - Item * m_buffer; - std::atomic < unsigned int > m_write_state[size + 1]; - }; +private: + Item* m_buffer; + std::atomic m_write_state[size + 1]; +}; - class QueueBuffer : public BufferBase - { - public: - QueueBuffer(QueueBuffer const &) = delete; - QueueBuffer& operator=(QueueBuffer const &) = delete; - - QueueBuffer() : m_current_read_buffer{nullptr} - , m_write_index(0) - , m_flag() - , m_read_index(0) +class QueueBuffer : public BufferBase { +public: + QueueBuffer(QueueBuffer const&) = delete; + QueueBuffer& operator=(QueueBuffer const&) = delete; + + QueueBuffer() + : m_current_read_buffer{nullptr}, + m_write_index(0), + m_flag(), + m_read_index(0) { setup_next_write_buffer(); } - void push(VDebug && logline) override - { - unsigned int write_index = m_write_index.fetch_add(1, std::memory_order_relaxed); - if (write_index < Buffer::size) - { - if (m_current_write_buffer.load(std::memory_order_acquire)->push(std::move(logline), write_index)) - { - setup_next_write_buffer(); - } - } - else - { - while (m_write_index.load(std::memory_order_acquire) >= Buffer::size); - push(std::move(logline)); - } + void push(VDebug&& logline) override + { + unsigned int write_index = + m_write_index.fetch_add(1, std::memory_order_relaxed); + if (write_index < Buffer::size) { + if (m_current_write_buffer.load(std::memory_order_acquire) + ->push(std::move(logline), write_index)) { + setup_next_write_buffer(); + } + } else { + while (m_write_index.load(std::memory_order_acquire) >= + Buffer::size) + ; + push(std::move(logline)); } + } - bool try_pop(VDebug & logline) override + bool try_pop(VDebug& logline) override { if (m_current_read_buffer == nullptr) - m_current_read_buffer = get_next_read_buffer(); + m_current_read_buffer = get_next_read_buffer(); - Buffer * read_buffer = m_current_read_buffer; + Buffer* read_buffer = m_current_read_buffer; - if (read_buffer == nullptr) - return false; + if (read_buffer == nullptr) return false; - if (bool success = read_buffer->try_pop(logline, m_read_index)) - { - m_read_index++; - if (m_read_index == Buffer::size) - { - m_read_index = 0; - m_current_read_buffer = nullptr; - SpinLock spinlock(m_flag); - m_buffers.pop(); - } - return true; + if (bool success = read_buffer->try_pop(logline, m_read_index)) { + m_read_index++; + if (m_read_index == Buffer::size) { + m_read_index = 0; + m_current_read_buffer = nullptr; + SpinLock spinlock(m_flag); + m_buffers.pop(); + } + return true; } return false; } - private: +private: void setup_next_write_buffer() { - std::unique_ptr < Buffer > next_write_buffer(new Buffer()); - m_current_write_buffer.store(next_write_buffer.get(), std::memory_order_release); + std::unique_ptr next_write_buffer(new Buffer()); + m_current_write_buffer.store(next_write_buffer.get(), + std::memory_order_release); SpinLock spinlock(m_flag); m_buffers.push(std::move(next_write_buffer)); m_write_index.store(0, std::memory_order_relaxed); } - Buffer * get_next_read_buffer() + Buffer* get_next_read_buffer() { SpinLock spinlock(m_flag); return m_buffers.empty() ? nullptr : m_buffers.front().get(); } - private: - std::queue < std::unique_ptr < Buffer > > m_buffers; - std::atomic < Buffer * > m_current_write_buffer; - Buffer * m_current_read_buffer; - std::atomic < unsigned int > m_write_index; - std::atomic_flag m_flag; - unsigned int m_read_index; - }; +private: + std::queue > m_buffers; + std::atomic m_current_write_buffer; + Buffer* m_current_read_buffer; + std::atomic m_write_index; + std::atomic_flag m_flag; + unsigned int m_read_index; +}; - class FileWriter - { - public: - FileWriter(std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb) - : m_log_file_roll_size_bytes(log_file_roll_size_mb * 1024 * 1024) - , m_name(log_directory + log_file_name) +class FileWriter { +public: + FileWriter(std::string const& log_directory, + std::string const& log_file_name, uint32_t log_file_roll_size_mb) + : m_log_file_roll_size_bytes(log_file_roll_size_mb * 1024 * 1024), + m_name(log_directory + log_file_name) { roll_file(); } - void write(VDebug & logline) + void write(VDebug& logline) { auto pos = m_os->tellp(); logline.stringify(*m_os); m_bytes_written += m_os->tellp() - pos; - if (m_bytes_written > m_log_file_roll_size_bytes) - { - roll_file(); + if (m_bytes_written > m_log_file_roll_size_bytes) { + roll_file(); } } - private: +private: void roll_file() { - if (m_os) - { - m_os->flush(); - m_os->close(); + if (m_os) { + m_os->flush(); + m_os->close(); } m_bytes_written = 0; @@ -588,31 +612,35 @@ namespace m_os->open(log_file_name, std::ofstream::out | std::ofstream::trunc); } - private: - uint32_t m_file_number = 0; - std::streamoff m_bytes_written = 0; - uint32_t const m_log_file_roll_size_bytes; - std::string const m_name; - std::unique_ptr < std::ofstream > m_os; - }; - - class NanoLogger - { - public: - NanoLogger(NonGuaranteedLogger ngl, std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb) - : m_state(State::INIT) - , m_buffer_base(new RingBuffer(std::max(1u, ngl.ring_buffer_size_mb) * 1024 * 4)) - , m_file_writer(log_directory, log_file_name, std::max(1u, log_file_roll_size_mb)) - , m_thread(&NanoLogger::pop, this) +private: + uint32_t m_file_number = 0; + std::streamoff m_bytes_written = 0; + uint32_t const m_log_file_roll_size_bytes; + std::string const m_name; + std::unique_ptr m_os; +}; + +class NanoLogger { +public: + NanoLogger(NonGuaranteedLogger ngl, std::string const& log_directory, + std::string const& log_file_name, uint32_t log_file_roll_size_mb) + : m_state(State::INIT), + m_buffer_base( + new RingBuffer(std::max(1u, ngl.ring_buffer_size_mb) * 1024 * 4)), + m_file_writer(log_directory, log_file_name, + std::max(1u, log_file_roll_size_mb)), + m_thread(&NanoLogger::pop, this) { m_state.store(State::READY, std::memory_order_release); } - NanoLogger(GuaranteedLogger gl, std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb) - : m_state(State::INIT) - , m_buffer_base(new QueueBuffer()) - , m_file_writer(log_directory, log_file_name, std::max(1u, log_file_roll_size_mb)) - , m_thread(&NanoLogger::pop, this) + NanoLogger(GuaranteedLogger gl, std::string const& log_directory, + std::string const& log_file_name, uint32_t log_file_roll_size_mb) + : m_state(State::INIT), + m_buffer_base(new QueueBuffer()), + m_file_writer(log_directory, log_file_name, + std::max(1u, log_file_roll_size_mb)), + m_thread(&NanoLogger::pop, this) { m_state.store(State::READY, std::memory_order_release); } @@ -623,97 +651,94 @@ namespace m_thread.join(); } - void add(VDebug && logline) - { - m_buffer_base->push(std::move(logline)); - } + void add(VDebug&& logline) { m_buffer_base->push(std::move(logline)); } void pop() { - // Wait for constructor to complete and pull all stores done there to this thread / core. + // Wait for constructor to complete and pull all stores done there to + // this thread / core. while (m_state.load(std::memory_order_acquire) == State::INIT) - std::this_thread::sleep_for(std::chrono::microseconds(50)); + std::this_thread::sleep_for(std::chrono::microseconds(50)); VDebug logline(LogLevel::INFO, nullptr, nullptr, 0); - while (m_state.load() == State::READY) - { - if (m_buffer_base->try_pop(logline)) - m_file_writer.write(logline); - else - std::this_thread::sleep_for(std::chrono::microseconds(50)); + while (m_state.load() == State::READY) { + if (m_buffer_base->try_pop(logline)) + m_file_writer.write(logline); + else + std::this_thread::sleep_for(std::chrono::microseconds(50)); } // Pop and log all remaining entries - while (m_buffer_base->try_pop(logline)) - { - m_file_writer.write(logline); + while (m_buffer_base->try_pop(logline)) { + m_file_writer.write(logline); } } - private: - enum class State - { - INIT, - READY, - SHUTDOWN - }; +private: + enum class State { INIT, READY, SHUTDOWN }; - std::atomic < State > m_state; - std::unique_ptr < BufferBase > m_buffer_base; - FileWriter m_file_writer; - std::thread m_thread; - }; + std::atomic m_state; + std::unique_ptr m_buffer_base; + FileWriter m_file_writer; + std::thread m_thread; +}; - std::unique_ptr < NanoLogger > nanologger; - std::atomic < NanoLogger * > atomic_nanologger; +std::unique_ptr nanologger; +std::atomic atomic_nanologger; - bool VDebugServer::operator==(VDebug & logline) - { +bool VDebugServer::operator==(VDebug& logline) +{ atomic_nanologger.load(std::memory_order_acquire)->add(std::move(logline)); return true; - } +} - void initialize(NonGuaranteedLogger ngl, std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb) - { - nanologger.reset(new NanoLogger(ngl, log_directory, log_file_name, log_file_roll_size_mb)); +void initialize(NonGuaranteedLogger ngl, std::string const& log_directory, + std::string const& log_file_name, + uint32_t log_file_roll_size_mb) +{ + nanologger.reset(new NanoLogger(ngl, log_directory, log_file_name, + log_file_roll_size_mb)); atomic_nanologger.store(nanologger.get(), std::memory_order_seq_cst); - } +} - void initialize(GuaranteedLogger gl, std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb) - { - nanologger.reset(new NanoLogger(gl, log_directory, log_file_name, log_file_roll_size_mb)); +void initialize(GuaranteedLogger gl, std::string const& log_directory, + std::string const& log_file_name, + uint32_t log_file_roll_size_mb) +{ + nanologger.reset(new NanoLogger(gl, log_directory, log_file_name, + log_file_roll_size_mb)); atomic_nanologger.store(nanologger.get(), std::memory_order_seq_cst); - } +} - std::atomic < unsigned int > loglevel = {0}; +std::atomic loglevel = {0}; - void set_log_level(LogLevel level) - { +void set_log_level(LogLevel level) +{ loglevel.store(static_cast(level), std::memory_order_release); - } +} - bool is_logged(LogLevel level) - { - return static_cast(level) >= loglevel.load(std::memory_order_relaxed); - } +bool is_logged(LogLevel level) +{ + return static_cast(level) >= + loglevel.load(std::memory_order_relaxed); +} - void initDebug() - { - initialize(GuaranteedLogger(), "/tmp/", "lotti-player", 1); - set_log_level(LogLevel::INFO); - } +void initDebug() +{ + initialize(GuaranteedLogger(), "/tmp/", "lotti-player", 1); + set_log_level(LogLevel::INFO); +} #ifndef DEBUG_CONSTRUCTOR_FUNCTION -# define DEBUG_CONSTRUCTOR_FUNCTION0(AFUNC) \ - namespace { \ - static const struct AFUNC ## _ctor_class_ { \ - inline AFUNC ## _ctor_class_() { AFUNC(); } \ - } AFUNC ## _ctor_instance_; \ +#define DEBUG_CONSTRUCTOR_FUNCTION0(AFUNC) \ + namespace { \ + static const struct AFUNC##_ctor_class_ { \ + inline AFUNC##_ctor_class_() { AFUNC(); } \ + } AFUNC##_ctor_instance_; \ } -# define DEBUG_CONSTRUCTOR_FUNCTION(AFUNC) DEBUG_CONSTRUCTOR_FUNCTION0(AFUNC) +#define DEBUG_CONSTRUCTOR_FUNCTION(AFUNC) DEBUG_CONSTRUCTOR_FUNCTION0(AFUNC) #endif - DEBUG_CONSTRUCTOR_FUNCTION(initDebug) - +DEBUG_CONSTRUCTOR_FUNCTION(initDebug) diff --git a/src/vector/vdebug.h b/src/vector/vdebug.h index 536bc48..c1ae239 100644 --- a/src/vector/vdebug.h +++ b/src/vector/vdebug.h @@ -1,103 +1,103 @@ #ifndef VDEBUG_H #define VDEBUG_H #include +#include #include #include -#include #include - - enum class LogLevel : uint8_t { INFO, WARN, CRIT, OFF }; - -class VDebug -{ +class VDebug { public: VDebug(); - VDebug& debug() {return *this;} - VDebug(LogLevel level, char const * file, char const * function, uint32_t line); + VDebug& debug() { return *this; } + VDebug(LogLevel level, char const* file, char const* function, + uint32_t line); ~VDebug(); - VDebug(VDebug &&) = default; - VDebug& operator=(VDebug &&) = default; + VDebug(VDebug&&) = default; + VDebug& operator=(VDebug&&) = default; - void stringify(std::ostream & os); + void stringify(std::ostream& os); VDebug& operator<<(char arg); VDebug& operator<<(int32_t arg); VDebug& operator<<(uint32_t arg); - //VDebug& operator<<(int64_t arg); - //VDebug& operator<<(uint64_t arg); + // VDebug& operator<<(int64_t arg); + // VDebug& operator<<(uint64_t arg); VDebug& operator<<(long arg); VDebug& operator<<(unsigned long arg); VDebug& operator<<(double arg); - VDebug& operator<<(std::string const & arg); + VDebug& operator<<(std::string const& arg); - template < size_t N > - VDebug& operator<<(const char (&arg)[N]) { + template + VDebug& operator<<(const char (&arg)[N]) + { encode(string_literal_t(arg)); return *this; } - template < typename Arg > - typename std::enable_if < std::is_same < Arg, char const * >::value, VDebug& >::type - operator<<(Arg const & arg) { + template + typename std::enable_if::value, + VDebug&>::type + operator<<(Arg const& arg) + { encode(arg); return *this; } - template < typename Arg > - typename std::enable_if < std::is_same < Arg, char * >::value, VDebug& >::type - operator<<(Arg const & arg) { + template + typename std::enable_if::value, VDebug&>::type + operator<<(Arg const& arg) + { encode(arg); return *this; } struct string_literal_t { - explicit string_literal_t(char const * s) : m_s(s) {} - char const * m_s; + explicit string_literal_t(char const* s) : m_s(s) {} + char const* m_s; }; private: - char * buffer(); + char* buffer(); - template < typename Arg > + template void encode(Arg arg); - template < typename Arg > + template void encode(Arg arg, uint8_t type_id); - void encode(char * arg); - void encode(char const * arg); + void encode(char* arg); + void encode(char const* arg); void encode(string_literal_t arg); - void encode_c_string(char const * arg, size_t length); + void encode_c_string(char const* arg, size_t length); void resize_buffer_if_needed(size_t additional_bytes); - void stringify(std::ostream & os, char * start, char const * const end); + void stringify(std::ostream& os, char* start, char const* const end); private: - size_t m_bytes_used; - size_t m_buffer_size; - std::unique_ptr < char [] > m_heap_buffer; - bool m_logAll; - char m_stack_buffer[256 - sizeof(bool) - 2 * sizeof(size_t) - sizeof(decltype(m_heap_buffer)) - 8 /* Reserved */]; + size_t m_bytes_used; + size_t m_buffer_size; + std::unique_ptr m_heap_buffer; + bool m_logAll; + char m_stack_buffer[256 - sizeof(bool) - 2 * sizeof(size_t) - + sizeof(decltype(m_heap_buffer)) - 8 /* Reserved */]; }; -struct VDebugServer -{ +struct VDebugServer { /* * Ideally this should have been operator+= * Could not get that to compile, so here we are... */ - bool operator==(VDebug &); + bool operator==(VDebug&); }; void set_log_level(LogLevel level); bool is_logged(LogLevel level); - /* * Non guaranteed logging. Uses a ring buffer to hold log lines. * When the ring gets full, the previous log line in the slot will be dropped. @@ -106,17 +106,18 @@ bool is_logged(LogLevel level); * is determined by this parameter. Since each LogLine is 256 bytes, * ring_buffer_size = ring_buffer_size_mb * 1024 * 1024 / 256 */ -struct NonGuaranteedLogger -{ - NonGuaranteedLogger(uint32_t ring_buffer_size_mb_) : ring_buffer_size_mb(ring_buffer_size_mb_) {} +struct NonGuaranteedLogger { + NonGuaranteedLogger(uint32_t ring_buffer_size_mb_) + : ring_buffer_size_mb(ring_buffer_size_mb_) + { + } uint32_t ring_buffer_size_mb; }; /* * Provides a guarantee log lines will not be dropped. */ -struct GuaranteedLogger -{ +struct GuaranteedLogger { }; /* @@ -129,15 +130,17 @@ struct GuaranteedLogger * etc. * log_file_roll_size_mb - mega bytes after which we roll to next log file. */ -void initialize(GuaranteedLogger gl, std::string const & log_directory, - std::string const & log_file_name, uint32_t log_file_roll_size_mb); -void initialize(NonGuaranteedLogger ngl, std::string const & log_directory, - std::string const & log_file_name, uint32_t log_file_roll_size_mb); - - -#define VDEBUG_LOG(LEVEL) VDebugServer() == VDebug(LEVEL, __FILE__, __func__, __LINE__).debug() +void initialize(GuaranteedLogger gl, std::string const& log_directory, + std::string const& log_file_name, + uint32_t log_file_roll_size_mb); +void initialize(NonGuaranteedLogger ngl, std::string const& log_directory, + std::string const& log_file_name, + uint32_t log_file_roll_size_mb); + +#define VDEBUG_LOG(LEVEL) \ + VDebugServer() == VDebug(LEVEL, __FILE__, __func__, __LINE__).debug() #define vDebug is_logged(LogLevel::INFO) && VDEBUG_LOG(LogLevel::INFO) #define vWarning is_logged(LogLevel::WARN) && VDEBUG_LOG(LogLevel::WARN) #define vCritical is_logged(LogLevel::CRIT) && VDEBUG_LOG(LogLevel::CRIT) -#endif // VDEBUG_H +#endif // VDEBUG_H diff --git a/src/vector/vdrawable.cpp b/src/vector/vdrawable.cpp index f057c1f..89be798 100644 --- a/src/vector/vdrawable.cpp +++ b/src/vector/vdrawable.cpp @@ -1,6 +1,6 @@ #include "vdrawable.h" -#include"vdasher.h" -#include"vraster.h" +#include "vdasher.h" +#include "vraster.h" void VDrawable::preprocess() { @@ -11,8 +11,9 @@ void VDrawable::preprocess() VDasher dasher(mStroke.dashArray, mStroke.dashArraySize); newPath = dasher.dashed(mPath); } - mRleTask = VRaster::instance().generateStrokeInfo(newPath, mStroke.cap, mStroke.join, - mStroke.width, mStroke.meterLimit); + mRleTask = VRaster::instance().generateStrokeInfo( + newPath, mStroke.cap, mStroke.join, mStroke.width, + mStroke.meterLimit); } else { mRleTask = VRaster::instance().generateFillInfo(mPath, mFillRule); } @@ -28,7 +29,8 @@ VRle VDrawable::rle() return mRle; } -void VDrawable::setStrokeInfo(CapStyle cap, JoinStyle join, float meterLimit, float strokeWidth) +void VDrawable::setStrokeInfo(CapStyle cap, JoinStyle join, float meterLimit, + float strokeWidth) { mStroke.enable = true; mStroke.cap = cap; diff --git a/src/vector/vdrawable.h b/src/vector/vdrawable.h index 8e8b3ac..a518cd4 100644 --- a/src/vector/vdrawable.h +++ b/src/vector/vdrawable.h @@ -1,19 +1,18 @@ #ifndef VDRAWABLE_H #define VDRAWABLE_H +#include #include "vbrush.h" #include "vpath.h" #include "vrle.h" -#include -class VDrawable -{ +class VDrawable { public: enum class DirtyState { - None = 0x00000000, - Path = 0x00000001, - Stroke = 0x00000010, - Brush = 0x00000100, - All = (None | Path | Stroke | Brush) + None = 0x00000000, + Path = 0x00000001, + Stroke = 0x00000010, + Brush = 0x00000100, + All = (None | Path | Stroke | Brush) }; enum class Type { Fill, @@ -22,29 +21,31 @@ public: typedef vFlag DirtyFlag; VDrawable() = default; void setPath(const VPath &path); - void setFillRule(FillRule rule){mFillRule = rule;} - void setBrush(const VBrush &brush){mBrush = brush;} - void setStrokeInfo(CapStyle cap, JoinStyle join, float meterLimit, float strokeWidth); + void setFillRule(FillRule rule) { mFillRule = rule; } + void setBrush(const VBrush &brush) { mBrush = brush; } + void setStrokeInfo(CapStyle cap, JoinStyle join, float meterLimit, + float strokeWidth); void setDashInfo(float *array, int size); void preprocess(); VRle rle(); + public: - DirtyFlag mFlag {DirtyState::All}; - VDrawable::Type mType {Type::Fill}; - VBrush mBrush; - VPath mPath; - FillRule mFillRule{FillRule::Winding}; - std::future mRleTask; - VRle mRle; - struct { - bool enable {false}; - float width {0.0}; - CapStyle cap {CapStyle::Flat}; - JoinStyle join {JoinStyle::Bevel}; - float meterLimit {10}; - float *dashArray {nullptr}; - int dashArraySize {0}; - }mStroke; + DirtyFlag mFlag{DirtyState::All}; + VDrawable::Type mType{Type::Fill}; + VBrush mBrush; + VPath mPath; + FillRule mFillRule{FillRule::Winding}; + std::future mRleTask; + VRle mRle; + struct { + bool enable{false}; + float width{0.0}; + CapStyle cap{CapStyle::Flat}; + JoinStyle join{JoinStyle::Bevel}; + float meterLimit{10}; + float * dashArray{nullptr}; + int dashArraySize{0}; + } mStroke; }; -#endif // VDRAWABLE_H +#endif // VDRAWABLE_H diff --git a/src/vector/vdrawhelper.cpp b/src/vector/vdrawhelper.cpp index 69b13b2..bec2410 100644 --- a/src/vector/vdrawhelper.cpp +++ b/src/vector/vdrawhelper.cpp @@ -1,27 +1,26 @@ -#include"vdrawhelper.h" -#include -#include -#include -#include +#include "vdrawhelper.h" +#include +#include +#include +#include - -class VGradientCache -{ +class VGradientCache { public: - struct CacheInfo : public VSpanData::Pinnable - { - inline CacheInfo(VGradientStops s):stops(s) {} - uint32_t buffer32[VGradient::colorTableSize]; + struct CacheInfo : public VSpanData::Pinnable { + inline CacheInfo(VGradientStops s) : stops(s) {} + uint32_t buffer32[VGradient::colorTableSize]; VGradientStops stops; bool alpha; }; - typedef std::unordered_multimap> VGradientColorTableHash; + typedef std::unordered_multimap> + VGradientColorTableHash; bool generateGradientColorTable(const VGradientStops &stops, uint32_t *colorTable, int size); - inline const std::shared_ptr getBuffer(const VGradient &gradient) + inline const std::shared_ptr getBuffer( + const VGradient &gradient) { - uint64_t hash_val = 0; + uint64_t hash_val = 0; std::shared_ptr info; const VGradientStops &stops = gradient.mStops; @@ -33,14 +32,14 @@ public: int count = cache.count(hash_val); if (!count) { // key is not present in the hash - info = addCacheElement(hash_val, gradient); + info = addCacheElement(hash_val, gradient); } else if (count == 1) { VGradientColorTableHash::const_iterator it = cache.find(hash_val); if (it->second->stops == stops) { info = it->second; } else { // didn't find an exact match - info = addCacheElement(hash_val, gradient); + info = addCacheElement(hash_val, gradient); } } else { // we have a multiple data with same key @@ -53,7 +52,7 @@ public: } if (!info) { // didn't find an exact match - info = addCacheElement(hash_val, gradient); + info = addCacheElement(hash_val, gradient); } } cacheAccess.unlock(); @@ -61,8 +60,9 @@ public: } protected: - inline uint maxCacheSize() const { return 60; } - const std::shared_ptr addCacheElement(uint64_t hash_val, const VGradient &gradient) + inline uint maxCacheSize() const { return 60; } + const std::shared_ptr addCacheElement( + uint64_t hash_val, const VGradient &gradient) { if (cache.size() == maxCacheSize()) { int count = rand() % maxCacheSize(); @@ -71,25 +71,25 @@ protected: } } auto cache_entry = std::make_shared(gradient.mStops); - cache_entry->alpha = generateGradientColorTable(gradient.mStops, cache_entry->buffer32, VGradient::colorTableSize); + cache_entry->alpha = generateGradientColorTable( + gradient.mStops, cache_entry->buffer32, VGradient::colorTableSize); cache.insert(std::make_pair(hash_val, cache_entry)); return cache_entry; } VGradientColorTableHash cache; - std::mutex cacheAccess; + std::mutex cacheAccess; }; -bool -VGradientCache::generateGradientColorTable(const VGradientStops &stops, - uint32_t *colorTable, int size) +bool VGradientCache::generateGradientColorTable(const VGradientStops &stops, + uint32_t *colorTable, int size) { - int dist, idist, pos = 0, i; - bool alpha = false; - int stopCount = stops.size(); + int dist, idist, pos = 0, i; + bool alpha = false; + int stopCount = stops.size(); const VGradientStop *curr, *next, *start; - uint32_t curColor, nextColor; - float delta, t, incr, fpos; + uint32_t curColor, nextColor; + float delta, t, incr, fpos; start = stops.data(); curr = start; @@ -106,40 +106,39 @@ VGradientCache::generateGradientColorTable(const VGradientStops &stops, fpos += incr; } - for (i = 0; i < stopCount - 1; ++i) { + for (i = 0; i < stopCount - 1; ++i) { curr = (start + i); next = (start + i + 1); - delta = 1/(next->first - curr->first); + delta = 1 / (next->first - curr->first); if (!next->second.isOpaque()) alpha = true; nextColor = next->second.premulARGB(); - while (fpos < next->first && pos < size) - { - t = (fpos - curr->first) * delta; - dist = (int)(255 * t); - idist = 255 - dist; - colorTable[pos] = INTERPOLATE_PIXEL_255(curColor, idist, nextColor, dist); - ++pos; - fpos += incr; - } + while (fpos < next->first && pos < size) { + t = (fpos - curr->first) * delta; + dist = (int)(255 * t); + idist = 255 - dist; + colorTable[pos] = + INTERPOLATE_PIXEL_255(curColor, idist, nextColor, dist); + ++pos; + fpos += incr; + } curColor = nextColor; - } + } - for (;pos < size; ++pos) - colorTable[pos] = curColor; + for (; pos < size; ++pos) colorTable[pos] = curColor; - // Make sure the last color stop is represented at the end of the table - colorTable[size-1] = curColor; - return alpha; + // Make sure the last color stop is represented at the end of the table + colorTable[size - 1] = curColor; + return alpha; } -static VGradientCache VGradientCacheInstance; +static VGradientCache VGradientCacheInstance; void VRasterBuffer::init() { - mBuffer = nullptr; - mWidth = 0; - mHeight = 0; - mCompositionMode = VPainter::CompModeSrcOver; + mBuffer = nullptr; + mWidth = 0; + mHeight = 0; + mCompositionMode = VPainter::CompModeSrcOver; } void VRasterBuffer::clear() @@ -156,23 +155,24 @@ VBitmap::Format VRasterBuffer::prepare(VBitmap *image) mBytesPerLine = image->stride(); mFormat = image->format(); - //drawHelper = qDrawHelper + format; + // drawHelper = qDrawHelper + format; return mFormat; } -void VSpanData::init(VRasterBuffer* image) +void VSpanData::init(VRasterBuffer *image) { mRasterBuffer = image; - mSystemClip = VRect(0,0, image->width(), image->height()); + mSystemClip = VRect(0, 0, image->width(), image->height()); mType = VSpanData::Type::None; mBlendFunc = nullptr; mUnclippedBlendFunc = nullptr; } -extern CompositionFunction COMP_functionForMode_C[]; -extern CompositionFunctionSolid COMP_functionForModeSolid_C[]; -static const CompositionFunction *functionForMode = COMP_functionForMode_C; -static const CompositionFunctionSolid *functionForModeSolid = COMP_functionForModeSolid_C; +extern CompositionFunction COMP_functionForMode_C[]; +extern CompositionFunctionSolid COMP_functionForModeSolid_C[]; +static const CompositionFunction * functionForMode = COMP_functionForMode_C; +static const CompositionFunctionSolid *functionForModeSolid = + COMP_functionForModeSolid_C; /* * Gradient Draw routines @@ -180,9 +180,9 @@ static const CompositionFunctionSolid *functionForModeSolid = COMP_functionForMo */ #define FIXPT_BITS 8 -#define FIXPT_SIZE (1<mGradient; v->dx = grad->linear.x2 - grad->linear.x1; @@ -196,8 +196,8 @@ getLinearGradientValues(LinearGradientValues *v, const VSpanData *data) } } -static inline void -getRadialGradientValues(RadialGradientValues *v, const VSpanData *data) +static inline void getRadialGradientValues(RadialGradientValues *v, + const VSpanData * data) { const VGradientData &gradient = data->mGradient; v->dx = gradient.radial.cx - gradient.radial.fx; @@ -206,68 +206,63 @@ getRadialGradientValues(RadialGradientValues *v, const VSpanData *data) v->dr = gradient.radial.cradius - gradient.radial.fradius; v->sqrfr = gradient.radial.fradius * gradient.radial.fradius; - v->a = v->dr * v->dr - v->dx*v->dx - v->dy*v->dy; + v->a = v->dr * v->dr - v->dx * v->dx - v->dy * v->dy; v->inv2a = 1 / (2 * v->a); v->extended = !vIsZero(gradient.radial.fradius) || v->a <= 0; } -static inline int -gradientClamp(const VGradientData *grad, int ipos) +static inline int gradientClamp(const VGradientData *grad, int ipos) { - int limit; + int limit; - if (grad->mSpread == VGradient::Spread::Repeat) - { + if (grad->mSpread == VGradient::Spread::Repeat) { ipos = ipos % VGradient::colorTableSize; ipos = ipos < 0 ? VGradient::colorTableSize + ipos : ipos; - } - else if (grad->mSpread == VGradient::Spread::Reflect) - { + } else if (grad->mSpread == VGradient::Spread::Reflect) { limit = VGradient::colorTableSize * 2; ipos = ipos % limit; ipos = ipos < 0 ? limit + ipos : ipos; ipos = ipos >= VGradient::colorTableSize ? limit - 1 - ipos : ipos; - } - else - { - if (ipos < 0) ipos = 0; + } else { + if (ipos < 0) + ipos = 0; else if (ipos >= VGradient::colorTableSize) - ipos = VGradient::colorTableSize - 1; - } - return ipos; + ipos = VGradient::colorTableSize - 1; + } + return ipos; } -static uint32_t -gradientPixelFixed(const VGradientData *grad, int fixed_pos) +static uint32_t gradientPixelFixed(const VGradientData *grad, int fixed_pos) { - int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; + int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; - return grad->mColorTable[gradientClamp(grad, ipos)]; + return grad->mColorTable[gradientClamp(grad, ipos)]; } -static inline uint32_t -gradientPixel(const VGradientData *grad, float pos) +static inline uint32_t gradientPixel(const VGradientData *grad, float pos) { - int ipos = (int)(pos * (VGradient::colorTableSize - 1) + (float)(0.5)); + int ipos = (int)(pos * (VGradient::colorTableSize - 1) + (float)(0.5)); - return grad->mColorTable[gradientClamp(grad, ipos)]; + return grad->mColorTable[gradientClamp(grad, ipos)]; } -void -fetch_linear_gradient(uint32_t *buffer, const Operator *op, const VSpanData *data, int y, int x, int length) +void fetch_linear_gradient(uint32_t *buffer, const Operator *op, + const VSpanData *data, int y, int x, int length) { - float t, inc; + float t, inc; const VGradientData *gradient = &data->mGradient; - bool affine = true; - float rx=0, ry=0; + bool affine = true; + float rx = 0, ry = 0; if (op->linear.l == 0) { t = inc = 0; } else { - rx = data->m21 * (y + float(0.5)) + data->m11 * (x + float(0.5)) + data->dx; - ry = data->m22 * (y + float(0.5)) + data->m12 * (x + float(0.5)) + data->dy; - t = op->linear.dx*rx + op->linear.dy*ry + op->linear.off; + rx = data->m21 * (y + float(0.5)) + data->m11 * (x + float(0.5)) + + data->dx; + ry = data->m22 * (y + float(0.5)) + data->m12 * (x + float(0.5)) + + data->dy; + t = op->linear.dx * rx + op->linear.dy * ry + op->linear.off; inc = op->linear.dx * data->m11 + op->linear.dy * data->m12; affine = !data->m13 && !data->m23; @@ -280,10 +275,11 @@ fetch_linear_gradient(uint32_t *buffer, const Operator *op, const VSpanData *dat const uint32_t *end = buffer + length; if (affine) { if (inc > float(-1e-5) && inc < float(1e-5)) { - memfill32(buffer, gradientPixelFixed(gradient, int(t * FIXPT_SIZE)), length); + memfill32(buffer, gradientPixelFixed(gradient, int(t * FIXPT_SIZE)), + length); } else { - if (t+inc*length < float(INT_MAX >> (FIXPT_BITS + 1)) && - t+inc*length > float(INT_MIN >> (FIXPT_BITS + 1))) { + if (t + inc * length < float(INT_MAX >> (FIXPT_BITS + 1)) && + t + inc * length > float(INT_MIN >> (FIXPT_BITS + 1))) { // we can use fixed point math int t_fixed = int(t * FIXPT_SIZE); int inc_fixed = int(inc * FIXPT_SIZE); @@ -295,18 +291,20 @@ fetch_linear_gradient(uint32_t *buffer, const Operator *op, const VSpanData *dat } else { // we have to fall back to float math while (buffer < end) { - *buffer = gradientPixel(gradient, t/VGradient::colorTableSize); + *buffer = + gradientPixel(gradient, t / VGradient::colorTableSize); t += inc; ++buffer; } } } - } else { // fall back to float math here as well - float rw = data->m23 * (y + float(0.5)) + data->m13 * (x + float(0.5)) + data->m33; + } else { // fall back to float math here as well + float rw = data->m23 * (y + float(0.5)) + data->m13 * (x + float(0.5)) + + data->m33; while (buffer < end) { - float x = rx/rw; - float y = ry/rw; - t = (op->linear.dx*x + op->linear.dy *y) + op->linear.off; + float x = rx / rw; + float y = ry / rw; + t = (op->linear.dx * x + op->linear.dy * y) + op->linear.off; *buffer = gradientPixel(gradient, t); rx += data->m11; @@ -325,9 +323,9 @@ static inline float radialDeterminant(float a, float b, float c) return (b * b) - (4 * a * c); } -static void fetch(uint32_t *buffer, uint32_t *end, - const Operator *op, const VSpanData *data, float det, - float delta_det, float delta_delta_det, float b, float delta_b) +static void fetch(uint32_t *buffer, uint32_t *end, const Operator *op, + const VSpanData *data, float det, float delta_det, + float delta_delta_det, float b, float delta_b) { if (op->radial.extended) { while (buffer < end) { @@ -357,7 +355,8 @@ static void fetch(uint32_t *buffer, uint32_t *end, } } -void fetch_radial_gradient(uint32_t *buffer, const Operator *op, const VSpanData *data, int y, int x, int length) +void fetch_radial_gradient(uint32_t *buffer, const Operator *op, + const VSpanData *data, int y, int x, int length) { // avoid division by zero if (vIsZero(op->radial.a)) { @@ -365,10 +364,10 @@ void fetch_radial_gradient(uint32_t *buffer, const Operator *op, const VSpanData return; } - float rx = data->m21 * (y + float(0.5)) - + data->dx + data->m11 * (x + float(0.5)); - float ry = data->m22 * (y + float(0.5)) - + data->dy + data->m12 * (x + float(0.5)); + float rx = + data->m21 * (y + float(0.5)) + data->dx + data->m11 * (x + float(0.5)); + float ry = + data->m22 * (y + float(0.5)) + data->dy + data->m12 * (x + float(0.5)); bool affine = !data->m13 && !data->m23; uint32_t *end = buffer + length; @@ -381,8 +380,10 @@ void fetch_radial_gradient(uint32_t *buffer, const Operator *op, const VSpanData const float delta_rx = data->m11; const float delta_ry = data->m12; - float b = 2*(op->radial.dr*data->mGradient.radial.fradius + rx * op->radial.dx + ry * op->radial.dy); - float delta_b = 2*(delta_rx * op->radial.dx + delta_ry * op->radial.dy); + float b = 2 * (op->radial.dr * data->mGradient.radial.fradius + + rx * op->radial.dx + ry * op->radial.dy); + float delta_b = + 2 * (delta_rx * op->radial.dx + delta_ry * op->radial.dy); const float b_delta_b = 2 * b * delta_b; const float delta_b_delta_b = 2 * delta_b * delta_b; @@ -394,19 +395,24 @@ void fetch_radial_gradient(uint32_t *buffer, const Operator *op, const VSpanData const float rxrxryry = rx * rx + ry * ry; const float delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry; - const float rx_plus_ry = 2*(rx * delta_rx + ry * delta_ry); + const float rx_plus_ry = 2 * (rx * delta_rx + ry * delta_ry); const float delta_rx_plus_ry = 2 * delta_rxrxryry; inv_a *= inv_a; - float det = (bb - 4 * op->radial.a * (op->radial.sqrfr - rxrxryry)) * inv_a; - float delta_det = (b_delta_b + delta_bb + 4 * op->radial.a * (rx_plus_ry + delta_rxrxryry)) * inv_a; - const float delta_delta_det = (delta_b_delta_b + 4 * op->radial.a * delta_rx_plus_ry) * inv_a; + float det = + (bb - 4 * op->radial.a * (op->radial.sqrfr - rxrxryry)) * inv_a; + float delta_det = (b_delta_b + delta_bb + + 4 * op->radial.a * (rx_plus_ry + delta_rxrxryry)) * + inv_a; + const float delta_delta_det = + (delta_b_delta_b + 4 * op->radial.a * delta_rx_plus_ry) * inv_a; - fetch(buffer, end, op, data, det, delta_det, delta_delta_det, b, delta_b); + fetch(buffer, end, op, data, det, delta_det, delta_delta_det, b, + delta_b); } else { - float rw = data->m23 * (y + float(0.5)) - + data->m33 + data->m13 * (x + float(0.5)); + float rw = data->m23 * (y + float(0.5)) + data->m33 + + data->m13 * (x + float(0.5)); while (buffer < end) { if (rw == 0) { @@ -415,8 +421,10 @@ void fetch_radial_gradient(uint32_t *buffer, const Operator *op, const VSpanData float invRw = 1 / rw; float gx = rx * invRw - data->mGradient.radial.fx; float gy = ry * invRw - data->mGradient.radial.fy; - float b = 2*(op->radial.dr*data->mGradient.radial.fradius + gx*op->radial.dx + gy*op->radial.dy); - float det = radialDeterminant(op->radial.a, b, op->radial.sqrfr - (gx*gx + gy*gy)); + float b = 2 * (op->radial.dr * data->mGradient.radial.fradius + + gx * op->radial.dx + gy * op->radial.dy); + float det = radialDeterminant( + op->radial.a, b, op->radial.sqrfr - (gx * gx + gy * gy)); uint32_t result = 0; if (det >= 0) { @@ -443,13 +451,13 @@ void fetch_radial_gradient(uint32_t *buffer, const Operator *op, const VSpanData } } - -static inline Operator getOperator(const VSpanData *data, const VRle::Span *spans, int spanCount) +static inline Operator getOperator(const VSpanData * data, + const VRle::Span *spans, int spanCount) { Operator op; - bool solidSource = false; + bool solidSource = false; - switch(data->mType) { + switch (data->mType) { case VSpanData::Type::Solid: solidSource = vAlpha(data->mSolid) & 0xFF; op.srcFetch = nullptr; @@ -478,22 +486,22 @@ static inline Operator getOperator(const VSpanData *data, const VRle::Span *span return op; } -static void -blendColorARGB(int count, const VRle::Span *spans, void *userData) +static void blendColorARGB(int count, const VRle::Span *spans, void *userData) { VSpanData *data = (VSpanData *)(userData); - Operator op = getOperator(data, spans, count); + Operator op = getOperator(data, spans, count); const uint color = data->mSolid; if (op.mode == VPainter::CompModeSrc) { // inline for performance while (count--) { - uint *target = ((uint *)data->mRasterBuffer->scanLine(spans->y)) + spans->x; + uint *target = + ((uint *)data->mRasterBuffer->scanLine(spans->y)) + spans->x; if (spans->coverage == 255) { memfill32(target, color, spans->len); } else { uint c = BYTE_MUL(color, spans->coverage); - int ialpha = 255 - spans->coverage; + int ialpha = 255 - spans->coverage; for (int i = 0; i < spans->len; ++i) target[i] = c + BYTE_MUL(target[i], ialpha); } @@ -503,26 +511,27 @@ blendColorARGB(int count, const VRle::Span *spans, void *userData) } while (count--) { - uint *target = ((uint *)data->mRasterBuffer->scanLine(spans->y)) + spans->x; + uint *target = + ((uint *)data->mRasterBuffer->scanLine(spans->y)) + spans->x; op.funcSolid(target, spans->len, color, spans->coverage); ++spans; } } #define BLEND_GRADIENT_BUFFER_SIZE 2048 -static void -blendGradientARGB(int count, const VRle::Span *spans, void *userData) +static void blendGradientARGB(int count, const VRle::Span *spans, + void *userData) { VSpanData *data = (VSpanData *)(userData); - Operator op = getOperator(data, spans, count); + Operator op = getOperator(data, spans, count); unsigned int buffer[BLEND_GRADIENT_BUFFER_SIZE]; - if (!op.srcFetch) - return; + if (!op.srcFetch) return; while (count--) { - uint *target = ((uint *)data->mRasterBuffer->scanLine(spans->y)) + spans->x; + uint *target = + ((uint *)data->mRasterBuffer->scanLine(spans->y)) + spans->x; int length = spans->len; while (length) { int l = std::min(length, BLEND_GRADIENT_BUFFER_SIZE); @@ -535,8 +544,8 @@ blendGradientARGB(int count, const VRle::Span *spans, void *userData) } } -void -VSpanData::setup(const VBrush &brush, VPainter::CompositionMode mode, int alpha) +void VSpanData::setup(const VBrush &brush, VPainter::CompositionMode mode, + int alpha) { switch (brush.type()) { case VBrush::Type::NoBrush: @@ -593,16 +602,15 @@ void VSpanData::setupMatrix(const VMatrix &matrix) dx = inv.mtx; dy = inv.mty; - //const bool affine = inv.isAffine(); -// fast_matrix = affine -// && m11 * m11 + m21 * m21 < 1e4 -// && m12 * m12 + m22 * m22 < 1e4 -// && fabs(dx) < 1e4 -// && fabs(dy) < 1e4; + // const bool affine = inv.isAffine(); + // fast_matrix = affine + // && m11 * m11 + m21 * m21 < 1e4 + // && m12 * m12 + m22 * m22 < 1e4 + // && fabs(dx) < 1e4 + // && fabs(dy) < 1e4; } -void -VSpanData::updateSpanFunc() +void VSpanData::updateSpanFunc() { switch (mType) { case VSpanData::Type::None: @@ -622,37 +630,43 @@ VSpanData::updateSpanFunc() } #if !defined(__SSE2__) && !defined(__ARM_NEON__) -void -memfill32(uint32_t *dest, uint32_t value, int length) +void memfill32(uint32_t *dest, uint32_t value, int length) { - int n; - - if (length <= 0) - return; - - // Cute hack to align future memcopy operation - // and do unroll the loop a bit. Not sure it is - // the most efficient, but will do for now. - n = (length + 7) / 8; - switch (length & 0x07) - { - case 0: do { *dest++ = value; - VECTOR_FALLTHROUGH; - case 7: *dest++ = value; - VECTOR_FALLTHROUGH; - case 6: *dest++ = value; - VECTOR_FALLTHROUGH; - case 5: *dest++ = value; - VECTOR_FALLTHROUGH; - case 4: *dest++ = value; - VECTOR_FALLTHROUGH; - case 3: *dest++ = value; - VECTOR_FALLTHROUGH; - case 2: *dest++ = value; - VECTOR_FALLTHROUGH; - case 1: *dest++ = value; + int n; + + if (length <= 0) return; + + // Cute hack to align future memcopy operation + // and do unroll the loop a bit. Not sure it is + // the most efficient, but will do for now. + n = (length + 7) / 8; + switch (length & 0x07) { + case 0: + do { + *dest++ = value; + VECTOR_FALLTHROUGH; + case 7: + *dest++ = value; + VECTOR_FALLTHROUGH; + case 6: + *dest++ = value; + VECTOR_FALLTHROUGH; + case 5: + *dest++ = value; + VECTOR_FALLTHROUGH; + case 4: + *dest++ = value; + VECTOR_FALLTHROUGH; + case 3: + *dest++ = value; + VECTOR_FALLTHROUGH; + case 2: + *dest++ = value; + VECTOR_FALLTHROUGH; + case 1: + *dest++ = value; } while (--n > 0); - } + } } #endif @@ -662,27 +676,37 @@ void vInitDrawhelperFunctions() #if defined(__ARM_NEON__) // update fast path for NEON - extern void comp_func_solid_SourceOver_neon(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha); - extern void comp_func_solid_Source_neon(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha); - - COMP_functionForModeSolid_C[VPainter::CompModeSrc] = comp_func_solid_Source_neon; - COMP_functionForModeSolid_C[VPainter::CompModeSrcOver] = comp_func_solid_SourceOver_neon; + extern void comp_func_solid_SourceOver_neon( + uint32_t * dest, int length, uint32_t color, uint32_t const_alpha); + extern void comp_func_solid_Source_neon( + uint32_t * dest, int length, uint32_t color, uint32_t const_alpha); + + COMP_functionForModeSolid_C[VPainter::CompModeSrc] = + comp_func_solid_Source_neon; + COMP_functionForModeSolid_C[VPainter::CompModeSrcOver] = + comp_func_solid_SourceOver_neon; #endif #if defined(__SSE2__) // update fast path for SSE2 - extern void comp_func_solid_SourceOver_sse2(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha); - extern void comp_func_solid_Source_sse2(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha); - extern void comp_func_Source_sse2(uint32_t *dest, const uint32_t *src, int length, uint32_t const_alpha); - extern void comp_func_SourceOver_sse2(uint32_t *dest, const uint32_t *src, int length, uint32_t const_alpha); - - COMP_functionForModeSolid_C[VPainter::CompModeSrc] = comp_func_solid_Source_sse2; - COMP_functionForModeSolid_C[VPainter::CompModeSrcOver] = comp_func_solid_SourceOver_sse2; + extern void comp_func_solid_SourceOver_sse2( + uint32_t * dest, int length, uint32_t color, uint32_t const_alpha); + extern void comp_func_solid_Source_sse2( + uint32_t * dest, int length, uint32_t color, uint32_t const_alpha); + extern void comp_func_Source_sse2(uint32_t * dest, const uint32_t *src, + int length, uint32_t const_alpha); + extern void comp_func_SourceOver_sse2(uint32_t * dest, const uint32_t *src, + int length, uint32_t const_alpha); + + COMP_functionForModeSolid_C[VPainter::CompModeSrc] = + comp_func_solid_Source_sse2; + COMP_functionForModeSolid_C[VPainter::CompModeSrcOver] = + comp_func_solid_SourceOver_sse2; COMP_functionForMode_C[VPainter::CompModeSrc] = comp_func_Source_sse2; - //COMP_functionForMode_C[VPainter::CompModeSrcOver] = comp_func_SourceOver_sse2; + // COMP_functionForMode_C[VPainter::CompModeSrcOver] = + // comp_func_SourceOver_sse2; #endif } V_CONSTRUCTOR_FUNCTION(vInitDrawhelperFunctions) - diff --git a/src/vector/vdrawhelper.h b/src/vector/vdrawhelper.h index b480705..3ca9c43 100644 --- a/src/vector/vdrawhelper.h +++ b/src/vector/vdrawhelper.h @@ -1,71 +1,76 @@ #ifndef VDRAWHELPER_H #define VDRAWHELPER_H -#include"vrect.h" -#include"vbrush.h" -#include"vrle.h" -#include"vpainter.h" -#include"vbitmap.h" -#include"assert.h" -#include +#include +#include "assert.h" +#include "vbitmap.h" +#include "vbrush.h" +#include "vpainter.h" +#include "vrect.h" +#include "vrle.h" V_USE_NAMESPACE struct VSpanData; struct Operator; -typedef void (*CompositionFunctionSolid)(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha); -typedef void (*CompositionFunction)(uint32_t *dest, const uint32_t *src, int length, uint32_t const_alpha); -typedef void (*SourceFetchProc)(uint32_t *buffer, const Operator *o, const VSpanData *data, int y, int x, int length); -typedef void (*ProcessRleSpan)(int count, const VRle::Span *spans, void *userData); +typedef void (*CompositionFunctionSolid)(uint32_t *dest, int length, + uint32_t color, uint32_t const_alpha); +typedef void (*CompositionFunction)(uint32_t *dest, const uint32_t *src, + int length, uint32_t const_alpha); +typedef void (*SourceFetchProc)(uint32_t *buffer, const Operator *o, + const VSpanData *data, int y, int x, + int length); +typedef void (*ProcessRleSpan)(int count, const VRle::Span *spans, + void *userData); extern void memfill32(uint32_t *dest, uint32_t value, int count); - -struct LinearGradientValues -{ +struct LinearGradientValues { float dx; float dy; float l; float off; }; -struct RadialGradientValues -{ +struct RadialGradientValues { float dx; float dy; float dr; float sqrfr; float a; float inv2a; - bool extended; + bool extended; }; -struct Operator -{ +struct Operator { VPainter::CompositionMode mode; - SourceFetchProc srcFetch; - CompositionFunctionSolid funcSolid; - CompositionFunction func; + SourceFetchProc srcFetch; + CompositionFunctionSolid funcSolid; + CompositionFunction func; union { LinearGradientValues linear; RadialGradientValues radial; }; }; -class VRasterBuffer -{ +class VRasterBuffer { public: - VRasterBuffer(){ init();} - void init(); + VRasterBuffer() { init(); } + void init(); VBitmap::Format prepare(VBitmap *image); - void prepare(int w, int h); - void prepareBuffer(int w, int h); - void clear(); + void prepare(int w, int h); + void prepareBuffer(int w, int h); + void clear(); - void resetBuffer(int val=0); + void resetBuffer(int val = 0); - inline uchar *scanLine(int y) { assert(y>=0); assert(y= 0); + assert(y < mHeight); + return mBuffer + y * mBytesPerLine; + } int width() const { return mWidth; } int height() const { return mHeight; } @@ -74,18 +79,18 @@ public: uchar *buffer() const { return mBuffer; } - VBitmap::Format mFormat; + VBitmap::Format mFormat; VPainter::CompositionMode mCompositionMode; + private: - int mWidth; - int mHeight; - int mBytesPerLine; - int mBytesPerPixel; + int mWidth; + int mHeight; + int mBytesPerLine; + int mBytesPerPixel; uchar *mBuffer; }; -struct VGradientData -{ +struct VGradientData { VGradient::Spread mSpread; union { struct { @@ -95,90 +100,91 @@ struct VGradientData float cx, cy, fx, fy, cradius, fradius; } radial; }; - const uint32_t *mColorTable; - bool mColorTableAlpha; + const uint32_t *mColorTable; + bool mColorTableAlpha; }; -struct VSpanData -{ +struct VSpanData { class Pinnable { protected: ~Pinnable() {} }; - enum class Type { - None, - Solid, - LinearGradient, - RadialGradient - }; + enum class Type { None, Solid, LinearGradient, RadialGradient }; void updateSpanFunc(); - void init(VRasterBuffer* image); - void setup(const VBrush &brush, VPainter::CompositionMode mode=VPainter::CompModeSrcOver, int alpha=255); + void init(VRasterBuffer *image); + void setup(const VBrush & brush, + VPainter::CompositionMode mode = VPainter::CompModeSrcOver, + int alpha = 255); void setupMatrix(const VMatrix &matrix); - VRasterBuffer *mRasterBuffer; - ProcessRleSpan mBlendFunc; - ProcessRleSpan mUnclippedBlendFunc; - VRect mSystemClip; - VSpanData::Type mType; + VRasterBuffer * mRasterBuffer; + ProcessRleSpan mBlendFunc; + ProcessRleSpan mUnclippedBlendFunc; + VRect mSystemClip; + VSpanData::Type mType; std::shared_ptr mCachedGradient; union { - uint32_t mSolid; - VGradientData mGradient; + uint32_t mSolid; + VGradientData mGradient; }; - float m11, m12, m13, m21, m22, m23, m33, dx, dy; // inverse xform matrix + float m11, m12, m13, m21, m22, m23, m33, dx, dy; // inverse xform matrix }; -void vInitDrawhelperFunctions(); +void vInitDrawhelperFunctions(); extern void vInitBlendFunctions(); -#define BYTE_MUL(c, a) \ - ( (((((c) >> 8) & 0x00ff00ff) * (a)) & 0xff00ff00) + \ - (((((c) & 0x00ff00ff) * (a)) >> 8) & 0x00ff00ff) ) +#define BYTE_MUL(c, a) \ + ((((((c) >> 8) & 0x00ff00ff) * (a)) & 0xff00ff00) + \ + (((((c)&0x00ff00ff) * (a)) >> 8) & 0x00ff00ff)) inline constexpr int vRed(uint32_t c) -{ return ((c >> 16) & 0xff); } +{ + return ((c >> 16) & 0xff); +} inline constexpr int vGreen(uint32_t c) -{ return ((c >> 8) & 0xff); } +{ + return ((c >> 8) & 0xff); +} inline constexpr int vBlue(uint32_t c) -{ return (c & 0xff); } +{ + return (c & 0xff); +} inline constexpr int vAlpha(uint32_t c) -{ return c >> 24; } - -static inline uint -INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { - uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; - t >>= 8; - t &= 0xff00ff; - x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; - x &= 0xff00ff00; - x |= t; - return x; + return c >> 24; } - +static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) +{ + uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; + t >>= 8; + t &= 0xff00ff; + x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; + x &= 0xff00ff00; + x |= t; + return x; +} #define LOOP_ALIGNED_U1_A4(DEST, LENGTH, UOP, A4OP) \ - { \ - while((uintptr_t)DEST & 0xF && LENGTH) UOP \ - \ - while(LENGTH) { \ - switch(LENGTH) { \ - case 3: \ - case 2: \ - case 1: \ - UOP \ - break; \ - default: \ - A4OP \ - break; \ - } \ - } \ - } - -#endif //QDRAWHELPER_P_H + { \ + while ((uintptr_t)DEST & 0xF && LENGTH) \ + UOP \ + \ + while (LENGTH) \ + { \ + switch (LENGTH) { \ + case 3: \ + case 2: \ + case 1: \ + UOP break; \ + default: \ + A4OP break; \ + } \ + } \ + } + +#endif // QDRAWHELPER_P_H diff --git a/src/vector/vdrawhelper_sse2.cpp b/src/vector/vdrawhelper_sse2.cpp index fe7f5da..c2133d3 100644 --- a/src/vector/vdrawhelper_sse2.cpp +++ b/src/vector/vdrawhelper_sse2.cpp @@ -1,558 +1,498 @@ #if defined(__SSE2__) -#include"vdrawhelper.h" +#include "vdrawhelper.h" -#include /* for _mm_shuffle_pi16 and _MM_SHUFFLE */ #include /* for SSE2 intrinsics */ +#include /* for _mm_shuffle_pi16 and _MM_SHUFFLE */ // Each 32bits components of alphaChannel must be in the form 0x00AA00AA -inline static __m128i -v4_byte_mul_sse2(__m128i c, __m128i a) +inline static __m128i v4_byte_mul_sse2(__m128i c, __m128i a) { - const __m128i ag_mask = _mm_set1_epi32(0xFF00FF00); - const __m128i rb_mask = _mm_set1_epi32(0x00FF00FF); - - /* for AG */ - __m128i v_ag = _mm_and_si128(ag_mask, c); - v_ag = _mm_srli_epi32(v_ag, 8); - v_ag = _mm_mullo_epi16(a, v_ag); - v_ag = _mm_and_si128(ag_mask, v_ag); - - /* for RB */ - __m128i v_rb = _mm_and_si128(rb_mask, c); - v_rb = _mm_mullo_epi16(a, v_rb); - v_rb = _mm_srli_epi32(v_rb, 8); - v_rb = _mm_and_si128(rb_mask, v_rb); - - /* combine */ - return _mm_add_epi32(v_ag, v_rb); + const __m128i ag_mask = _mm_set1_epi32(0xFF00FF00); + const __m128i rb_mask = _mm_set1_epi32(0x00FF00FF); + + /* for AG */ + __m128i v_ag = _mm_and_si128(ag_mask, c); + v_ag = _mm_srli_epi32(v_ag, 8); + v_ag = _mm_mullo_epi16(a, v_ag); + v_ag = _mm_and_si128(ag_mask, v_ag); + + /* for RB */ + __m128i v_rb = _mm_and_si128(rb_mask, c); + v_rb = _mm_mullo_epi16(a, v_rb); + v_rb = _mm_srli_epi32(v_rb, 8); + v_rb = _mm_and_si128(rb_mask, v_rb); + + /* combine */ + return _mm_add_epi32(v_ag, v_rb); } -static inline __m128i -v4_ialpha_sse2(__m128i c) +static inline __m128i v4_ialpha_sse2(__m128i c) { - __m128i a = _mm_srli_epi32(c, 24); + __m128i a = _mm_srli_epi32(c, 24); - return _mm_sub_epi32(_mm_set1_epi32(0xff), a); + return _mm_sub_epi32(_mm_set1_epi32(0xff), a); } -static inline __m128i -v4_interpolate_color_sse2(__m128i a, __m128i c0, __m128i c1) +static inline __m128i v4_interpolate_color_sse2(__m128i a, __m128i c0, + __m128i c1) { - const __m128i rb_mask = _mm_set1_epi32(0xFF00FF00); - const __m128i zero = _mm_setzero_si128(); + const __m128i rb_mask = _mm_set1_epi32(0xFF00FF00); + const __m128i zero = _mm_setzero_si128(); - __m128i a_l = a; - __m128i a_h = a; - a_l = _mm_unpacklo_epi16(a_l, a_l); - a_h = _mm_unpackhi_epi16(a_h, a_h); + __m128i a_l = a; + __m128i a_h = a; + a_l = _mm_unpacklo_epi16(a_l, a_l); + a_h = _mm_unpackhi_epi16(a_h, a_h); - __m128i a_t = _mm_slli_epi64(a_l, 32); - __m128i a_t0 = _mm_slli_epi64(a_h, 32); + __m128i a_t = _mm_slli_epi64(a_l, 32); + __m128i a_t0 = _mm_slli_epi64(a_h, 32); - a_l = _mm_add_epi32(a_l, a_t); - a_h = _mm_add_epi32(a_h, a_t0); + a_l = _mm_add_epi32(a_l, a_t); + a_h = _mm_add_epi32(a_h, a_t0); - __m128i c0_l = c0; - __m128i c0_h = c0; + __m128i c0_l = c0; + __m128i c0_h = c0; - c0_l = _mm_unpacklo_epi8(c0_l, zero); - c0_h = _mm_unpackhi_epi8(c0_h, zero); + c0_l = _mm_unpacklo_epi8(c0_l, zero); + c0_h = _mm_unpackhi_epi8(c0_h, zero); - __m128i c1_l = c1; - __m128i c1_h = c1; + __m128i c1_l = c1; + __m128i c1_h = c1; - c1_l = _mm_unpacklo_epi8(c1_l, zero); - c1_h = _mm_unpackhi_epi8(c1_h, zero); + c1_l = _mm_unpacklo_epi8(c1_l, zero); + c1_h = _mm_unpackhi_epi8(c1_h, zero); - __m128i cl_sub = _mm_sub_epi16(c0_l, c1_l); - __m128i ch_sub = _mm_sub_epi16(c0_h, c1_h); + __m128i cl_sub = _mm_sub_epi16(c0_l, c1_l); + __m128i ch_sub = _mm_sub_epi16(c0_h, c1_h); - cl_sub = _mm_mullo_epi16(cl_sub, a_l); - ch_sub = _mm_mullo_epi16(ch_sub, a_h); + cl_sub = _mm_mullo_epi16(cl_sub, a_l); + ch_sub = _mm_mullo_epi16(ch_sub, a_h); - __m128i c1ls = _mm_slli_epi16(c1_l, 8); - __m128i c1hs = _mm_slli_epi16(c1_h, 8); + __m128i c1ls = _mm_slli_epi16(c1_l, 8); + __m128i c1hs = _mm_slli_epi16(c1_h, 8); - cl_sub = _mm_add_epi16(cl_sub, c1ls); - ch_sub = _mm_add_epi16(ch_sub, c1hs); + cl_sub = _mm_add_epi16(cl_sub, c1ls); + ch_sub = _mm_add_epi16(ch_sub, c1hs); - cl_sub = _mm_and_si128(cl_sub, rb_mask); - ch_sub = _mm_and_si128(ch_sub, rb_mask); + cl_sub = _mm_and_si128(cl_sub, rb_mask); + ch_sub = _mm_and_si128(ch_sub, rb_mask); - cl_sub = _mm_srli_epi64(cl_sub, 8); - ch_sub = _mm_srli_epi64(ch_sub, 8); + cl_sub = _mm_srli_epi64(cl_sub, 8); + ch_sub = _mm_srli_epi64(ch_sub, 8); - cl_sub = _mm_packus_epi16(cl_sub, cl_sub); - ch_sub = _mm_packus_epi16(ch_sub, ch_sub); + cl_sub = _mm_packus_epi16(cl_sub, cl_sub); + ch_sub = _mm_packus_epi16(ch_sub, ch_sub); - return (__m128i) _mm_shuffle_ps( (__m128)cl_sub, (__m128)ch_sub, 0x44); + return (__m128i)_mm_shuffle_ps((__m128)cl_sub, (__m128)ch_sub, 0x44); } - - // Load src and dest vector -#define V4_FETCH_SRC_DEST \ - __m128i v_src = _mm_loadu_si128((__m128i *)src); \ - __m128i v_dest = _mm_load_si128((__m128i *)dest); +#define V4_FETCH_SRC_DEST \ + __m128i v_src = _mm_loadu_si128((__m128i*)src); \ + __m128i v_dest = _mm_load_si128((__m128i*)dest); -#define V4_FETCH_SRC \ - __m128i v_src = _mm_loadu_si128((__m128i *)src); +#define V4_FETCH_SRC __m128i v_src = _mm_loadu_si128((__m128i*)src); -#define V4_STORE_DEST \ - _mm_store_si128((__m128i *)dest, v_src); +#define V4_STORE_DEST _mm_store_si128((__m128i*)dest, v_src); #define V4_SRC_DEST_LEN_INC \ - dest += 4; src +=4; length -= 4; + dest += 4; \ + src += 4; \ + length -= 4; // Multiply src color with const_alpha -#define V4_ALPHA_MULTIPLY \ - v_src = v4_byte_mul_sse2(v_src, v_alpha); +#define V4_ALPHA_MULTIPLY v_src = v4_byte_mul_sse2(v_src, v_alpha); // dest = src + dest * sia -#define V4_COMP_OP_SRC_OVER \ - __m128i v_sia = v4_ialpha_sse2(v_src); \ - v_sia = _mm_add_epi32(v_sia, _mm_slli_epi32(v_sia, 16)); \ - v_dest = v4_byte_mul_sse2(v_dest, v_sia); \ - v_src = _mm_add_epi32(v_src, v_dest); +#define V4_COMP_OP_SRC_OVER \ + __m128i v_sia = v4_ialpha_sse2(v_src); \ + v_sia = _mm_add_epi32(v_sia, _mm_slli_epi32(v_sia, 16)); \ + v_dest = v4_byte_mul_sse2(v_dest, v_sia); \ + v_src = _mm_add_epi32(v_src, v_dest); // dest = src + dest * sia #define V4_COMP_OP_SRC \ - v_src = v4_interpolate_color_sse2(v_alpha, v_src, v_dest); - + v_src = v4_interpolate_color_sse2(v_alpha, v_src, v_dest); -void -memfill32(uint32_t *dest, uint32_t value, int length) +void memfill32(uint32_t* dest, uint32_t value, int length) { __m128i vector_data = _mm_set_epi32(value, value, value, value); // run till memory alligned to 16byte memory - while (length && ((uintptr_t)dest & 0xf)) - { + while (length && ((uintptr_t)dest & 0xf)) { *dest++ = value; length--; } - while (length >= 32) - { - _mm_store_si128 ((__m128i*)(dest), vector_data); - _mm_store_si128 ((__m128i*)(dest + 4), vector_data); - _mm_store_si128 ((__m128i*)(dest + 8), vector_data); - _mm_store_si128 ((__m128i*)(dest + 12), vector_data); - _mm_store_si128 ((__m128i*)(dest + 16), vector_data); - _mm_store_si128 ((__m128i*)(dest + 20), vector_data); - _mm_store_si128 ((__m128i*)(dest + 24), vector_data); - _mm_store_si128 ((__m128i*)(dest + 28), vector_data); + while (length >= 32) { + _mm_store_si128((__m128i*)(dest), vector_data); + _mm_store_si128((__m128i*)(dest + 4), vector_data); + _mm_store_si128((__m128i*)(dest + 8), vector_data); + _mm_store_si128((__m128i*)(dest + 12), vector_data); + _mm_store_si128((__m128i*)(dest + 16), vector_data); + _mm_store_si128((__m128i*)(dest + 20), vector_data); + _mm_store_si128((__m128i*)(dest + 24), vector_data); + _mm_store_si128((__m128i*)(dest + 28), vector_data); dest += 32; length -= 32; } - if (length >= 16) - { - _mm_store_si128 ((__m128i*)(dest), vector_data); - _mm_store_si128 ((__m128i*)(dest + 4), vector_data); - _mm_store_si128 ((__m128i*)(dest + 8), vector_data); - _mm_store_si128 ((__m128i*)(dest + 12), vector_data); + if (length >= 16) { + _mm_store_si128((__m128i*)(dest), vector_data); + _mm_store_si128((__m128i*)(dest + 4), vector_data); + _mm_store_si128((__m128i*)(dest + 8), vector_data); + _mm_store_si128((__m128i*)(dest + 12), vector_data); dest += 16; length -= 16; } - if (length >= 8) - { - _mm_store_si128 ((__m128i*)(dest), vector_data); - _mm_store_si128 ((__m128i*)(dest + 4), vector_data); + if (length >= 8) { + _mm_store_si128((__m128i*)(dest), vector_data); + _mm_store_si128((__m128i*)(dest + 4), vector_data); dest += 8; length -= 8; } - if (length >= 4) - { - _mm_store_si128 ((__m128i*)(dest), vector_data); + if (length >= 4) { + _mm_store_si128((__m128i*)(dest), vector_data); dest += 4; length -= 4; } - while (length) - { + while (length) { *dest++ = value; length--; } } // dest = color + (dest * alpha) -inline static void -comp_func_helper_sse2(uint32_t *dest, int length, uint32_t color, uint32_t alpha) +inline static void comp_func_helper_sse2(uint32_t* dest, int length, + uint32_t color, uint32_t alpha) { - const __m128i v_color = _mm_set1_epi32(color); - const __m128i v_a = _mm_set1_epi16(alpha); - - LOOP_ALIGNED_U1_A4(dest, length, - { /* UOP */ - *dest = color + BYTE_MUL(*dest, alpha); - dest++; length--; - }, - { /* A4OP */ - __m128i v_dest = _mm_load_si128((__m128i *)dest); - - v_dest = v4_byte_mul_sse2(v_dest, v_a); - v_dest = _mm_add_epi32(v_dest, v_color); - - _mm_store_si128((__m128i *)dest, v_dest); - - dest += 4; length -= 4; - }) + const __m128i v_color = _mm_set1_epi32(color); + const __m128i v_a = _mm_set1_epi16(alpha); + + LOOP_ALIGNED_U1_A4(dest, length, + { /* UOP */ + *dest = color + BYTE_MUL(*dest, alpha); + dest++; + length--; + }, + { /* A4OP */ + __m128i v_dest = _mm_load_si128((__m128i*)dest); + + v_dest = v4_byte_mul_sse2(v_dest, v_a); + v_dest = _mm_add_epi32(v_dest, v_color); + + _mm_store_si128((__m128i*)dest, v_dest); + + dest += 4; + length -= 4; + }) } -void -comp_func_solid_Source_sse2(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha) +void comp_func_solid_Source_sse2(uint32_t* dest, int length, uint32_t color, + uint32_t const_alpha) { - if (const_alpha == 255) - { + if (const_alpha == 255) { memfill32(dest, color, length); - } - else - { + } else { int ialpha; ialpha = 255 - const_alpha; color = BYTE_MUL(color, const_alpha); comp_func_helper_sse2(dest, length, color, ialpha); - } + } } -void -comp_func_solid_SourceOver_sse2(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha) +void comp_func_solid_SourceOver_sse2(uint32_t* dest, int length, uint32_t color, + uint32_t const_alpha) { - int ialpha; + int ialpha; - if (const_alpha != 255) - color = BYTE_MUL(color, const_alpha); - ialpha = 255 - vAlpha(color); - comp_func_helper_sse2(dest, length, color, ialpha); + if (const_alpha != 255) color = BYTE_MUL(color, const_alpha); + ialpha = 255 - vAlpha(color); + comp_func_helper_sse2(dest, length, color, ialpha); } -void comp_func_Source_sse2(uint32_t *dest, const uint32_t *src, int length, uint32_t const_alpha) +void comp_func_Source_sse2(uint32_t* dest, const uint32_t* src, int length, + uint32_t const_alpha) { int ialpha; if (const_alpha == 255) { - memcpy(dest, src, length * sizeof(uint32_t)); + memcpy(dest, src, length * sizeof(uint32_t)); } else { ialpha = 255 - const_alpha; __m128i v_alpha = _mm_set1_epi32(const_alpha); LOOP_ALIGNED_U1_A4(dest, length, - { /* UOP */ - *dest = INTERPOLATE_PIXEL_255(*src, const_alpha, *dest, ialpha); - dest++; src++; length--; - }, - { /* A4OP */ - V4_FETCH_SRC_DEST - V4_COMP_OP_SRC - V4_STORE_DEST - V4_SRC_DEST_LEN_INC - }) + { /* UOP */ + *dest = INTERPOLATE_PIXEL_255(*src, const_alpha, + *dest, ialpha); + dest++; + src++; + length--; + }, + {/* A4OP */ + V4_FETCH_SRC_DEST V4_COMP_OP_SRC V4_STORE_DEST + V4_SRC_DEST_LEN_INC}) } } -void comp_func_SourceOver_sse2_1(uint32_t *dest, const uint32_t *src, int length, uint32_t const_alpha) +void comp_func_SourceOver_sse2_1(uint32_t* dest, const uint32_t* src, + int length, uint32_t const_alpha) { uint32_t s, sia; if (const_alpha == 255) { LOOP_ALIGNED_U1_A4(dest, length, - { /* UOP */ - s = *src; - sia = vAlpha(~s); - *dest = s + BYTE_MUL(*dest, sia); - dest++; src++; length--; - }, - { /* A4OP */ - V4_FETCH_SRC_DEST - V4_COMP_OP_SRC_OVER - V4_STORE_DEST - V4_SRC_DEST_LEN_INC - }) + { /* UOP */ + s = *src; + sia = vAlpha(~s); + *dest = s + BYTE_MUL(*dest, sia); + dest++; + src++; + length--; + }, + {/* A4OP */ + V4_FETCH_SRC_DEST V4_COMP_OP_SRC_OVER V4_STORE_DEST + V4_SRC_DEST_LEN_INC}) } else { __m128i v_alpha = _mm_set1_epi32(const_alpha); - LOOP_ALIGNED_U1_A4(dest, length, - { /* UOP */ - s = BYTE_MUL(*src, const_alpha); - sia = vAlpha(~s); - *dest = s + BYTE_MUL(*dest, sia); - dest++; src++; length--; - }, - { /* A4OP */ - V4_FETCH_SRC_DEST - V4_ALPHA_MULTIPLY - V4_COMP_OP_SRC_OVER - V4_STORE_DEST - V4_SRC_DEST_LEN_INC - }) + LOOP_ALIGNED_U1_A4( + dest, length, + { /* UOP */ + s = BYTE_MUL(*src, const_alpha); + sia = vAlpha(~s); + *dest = s + BYTE_MUL(*dest, sia); + dest++; + src++; + length--; + }, + {/* A4OP */ + V4_FETCH_SRC_DEST V4_ALPHA_MULTIPLY V4_COMP_OP_SRC_OVER + V4_STORE_DEST V4_SRC_DEST_LEN_INC}) } } // Pixman implementation #define force_inline inline -static force_inline __m128i -unpack_32_1x128 (uint32_t data) +static force_inline __m128i unpack_32_1x128(uint32_t data) { - return _mm_unpacklo_epi8 (_mm_cvtsi32_si128 (data), _mm_setzero_si128 ()); + return _mm_unpacklo_epi8(_mm_cvtsi32_si128(data), _mm_setzero_si128()); } -static force_inline void -unpack_128_2x128 (__m128i data, __m128i* data_lo, __m128i* data_hi) +static force_inline void unpack_128_2x128(__m128i data, __m128i* data_lo, + __m128i* data_hi) { - *data_lo = _mm_unpacklo_epi8 (data, _mm_setzero_si128 ()); - *data_hi = _mm_unpackhi_epi8 (data, _mm_setzero_si128 ()); + *data_lo = _mm_unpacklo_epi8(data, _mm_setzero_si128()); + *data_hi = _mm_unpackhi_epi8(data, _mm_setzero_si128()); } -static force_inline uint32_t -pack_1x128_32 (__m128i data) +static force_inline uint32_t pack_1x128_32(__m128i data) { - return _mm_cvtsi128_si32 (_mm_packus_epi16 (data, _mm_setzero_si128 ())); + return _mm_cvtsi128_si32(_mm_packus_epi16(data, _mm_setzero_si128())); } -static force_inline __m128i -pack_2x128_128 (__m128i lo, __m128i hi) +static force_inline __m128i pack_2x128_128(__m128i lo, __m128i hi) { - return _mm_packus_epi16 (lo, hi); + return _mm_packus_epi16(lo, hi); } /* load 4 pixels from a 16-byte boundary aligned address */ -static force_inline __m128i -load_128_aligned (__m128i* src) +static force_inline __m128i load_128_aligned(__m128i* src) { - return _mm_load_si128 (src); + return _mm_load_si128(src); } /* load 4 pixels from a unaligned address */ -static force_inline __m128i -load_128_unaligned (const __m128i* src) +static force_inline __m128i load_128_unaligned(const __m128i* src) { - return _mm_loadu_si128 (src); + return _mm_loadu_si128(src); } /* save 4 pixels on a 16-byte boundary aligned address */ -static force_inline void -save_128_aligned (__m128i* dst, - __m128i data) +static force_inline void save_128_aligned(__m128i* dst, __m128i data) { - _mm_store_si128 (dst, data); + _mm_store_si128(dst, data); } -static force_inline int -is_opaque (__m128i x) +static force_inline int is_opaque(__m128i x) { - __m128i ffs = _mm_cmpeq_epi8 (x, x); + __m128i ffs = _mm_cmpeq_epi8(x, x); - return (_mm_movemask_epi8 (_mm_cmpeq_epi8 (x, ffs)) & 0x8888) == 0x8888; + return (_mm_movemask_epi8(_mm_cmpeq_epi8(x, ffs)) & 0x8888) == 0x8888; } -static force_inline int -is_zero (__m128i x) +static force_inline int is_zero(__m128i x) { - return _mm_movemask_epi8 ( - _mm_cmpeq_epi8 (x, _mm_setzero_si128 ())) == 0xffff; + return _mm_movemask_epi8(_mm_cmpeq_epi8(x, _mm_setzero_si128())) == 0xffff; } -static force_inline __m128i -expand_alpha_1x128 (__m128i data) +static force_inline __m128i expand_alpha_1x128(__m128i data) { - return _mm_shufflehi_epi16 (_mm_shufflelo_epi16 (data, - _MM_SHUFFLE (3, 3, 3, 3)), - _MM_SHUFFLE (3, 3, 3, 3)); + return _mm_shufflehi_epi16( + _mm_shufflelo_epi16(data, _MM_SHUFFLE(3, 3, 3, 3)), + _MM_SHUFFLE(3, 3, 3, 3)); } -static force_inline __m128i -create_mask_16_128 (uint16_t mask) +static force_inline __m128i create_mask_16_128(uint16_t mask) { - return _mm_set1_epi16 (mask); + return _mm_set1_epi16(mask); } -static __m128i mask_0080 = create_mask_16_128 (0x0080); -static __m128i mask_00ff = create_mask_16_128 (0x00ff); -static __m128i mask_0101 = create_mask_16_128 (0x0101); +static __m128i mask_0080 = create_mask_16_128(0x0080); +static __m128i mask_00ff = create_mask_16_128(0x00ff); +static __m128i mask_0101 = create_mask_16_128(0x0101); -static force_inline __m128i -negate_1x128 (__m128i data) +static force_inline __m128i negate_1x128(__m128i data) { - return _mm_xor_si128 (data, mask_00ff); + return _mm_xor_si128(data, mask_00ff); } -static force_inline void -negate_2x128 (__m128i data_lo, - __m128i data_hi, - __m128i* neg_lo, - __m128i* neg_hi) +static force_inline void negate_2x128(__m128i data_lo, __m128i data_hi, + __m128i* neg_lo, __m128i* neg_hi) { - *neg_lo = _mm_xor_si128 (data_lo, mask_00ff); - *neg_hi = _mm_xor_si128 (data_hi, mask_00ff); + *neg_lo = _mm_xor_si128(data_lo, mask_00ff); + *neg_hi = _mm_xor_si128(data_hi, mask_00ff); } -static force_inline __m128i -pix_multiply_1x128 (__m128i data, - __m128i alpha) +static force_inline __m128i pix_multiply_1x128(__m128i data, __m128i alpha) { - return _mm_mulhi_epu16 (_mm_adds_epu16 (_mm_mullo_epi16 (data, alpha), - mask_0080), - mask_0101); + return _mm_mulhi_epu16( + _mm_adds_epu16(_mm_mullo_epi16(data, alpha), mask_0080), mask_0101); } -static force_inline void -pix_multiply_2x128 (__m128i* data_lo, - __m128i* data_hi, - __m128i* alpha_lo, - __m128i* alpha_hi, - __m128i* ret_lo, - __m128i* ret_hi) +static force_inline void pix_multiply_2x128(__m128i* data_lo, __m128i* data_hi, + __m128i* alpha_lo, + __m128i* alpha_hi, __m128i* ret_lo, + __m128i* ret_hi) { __m128i lo, hi; - lo = _mm_mullo_epi16 (*data_lo, *alpha_lo); - hi = _mm_mullo_epi16 (*data_hi, *alpha_hi); - lo = _mm_adds_epu16 (lo, mask_0080); - hi = _mm_adds_epu16 (hi, mask_0080); - *ret_lo = _mm_mulhi_epu16 (lo, mask_0101); - *ret_hi = _mm_mulhi_epu16 (hi, mask_0101); + lo = _mm_mullo_epi16(*data_lo, *alpha_lo); + hi = _mm_mullo_epi16(*data_hi, *alpha_hi); + lo = _mm_adds_epu16(lo, mask_0080); + hi = _mm_adds_epu16(hi, mask_0080); + *ret_lo = _mm_mulhi_epu16(lo, mask_0101); + *ret_hi = _mm_mulhi_epu16(hi, mask_0101); } -static force_inline __m128i -over_1x128 (__m128i src, __m128i alpha, __m128i dst) +static force_inline __m128i over_1x128(__m128i src, __m128i alpha, __m128i dst) { - return _mm_adds_epu8 (src, pix_multiply_1x128 (dst, negate_1x128 (alpha))); + return _mm_adds_epu8(src, pix_multiply_1x128(dst, negate_1x128(alpha))); } -static force_inline void -expand_alpha_2x128 (__m128i data_lo, - __m128i data_hi, - __m128i* alpha_lo, - __m128i* alpha_hi) +static force_inline void expand_alpha_2x128(__m128i data_lo, __m128i data_hi, + __m128i* alpha_lo, + __m128i* alpha_hi) { __m128i lo, hi; - lo = _mm_shufflelo_epi16 (data_lo, _MM_SHUFFLE (3, 3, 3, 3)); - hi = _mm_shufflelo_epi16 (data_hi, _MM_SHUFFLE (3, 3, 3, 3)); + lo = _mm_shufflelo_epi16(data_lo, _MM_SHUFFLE(3, 3, 3, 3)); + hi = _mm_shufflelo_epi16(data_hi, _MM_SHUFFLE(3, 3, 3, 3)); - *alpha_lo = _mm_shufflehi_epi16 (lo, _MM_SHUFFLE (3, 3, 3, 3)); - *alpha_hi = _mm_shufflehi_epi16 (hi, _MM_SHUFFLE (3, 3, 3, 3)); + *alpha_lo = _mm_shufflehi_epi16(lo, _MM_SHUFFLE(3, 3, 3, 3)); + *alpha_hi = _mm_shufflehi_epi16(hi, _MM_SHUFFLE(3, 3, 3, 3)); } -static force_inline void -over_2x128 (__m128i* src_lo, - __m128i* src_hi, - __m128i* alpha_lo, - __m128i* alpha_hi, - __m128i* dst_lo, - __m128i* dst_hi) +static force_inline void over_2x128(__m128i* src_lo, __m128i* src_hi, + __m128i* alpha_lo, __m128i* alpha_hi, + __m128i* dst_lo, __m128i* dst_hi) { __m128i t1, t2; - negate_2x128 (*alpha_lo, *alpha_hi, &t1, &t2); + negate_2x128(*alpha_lo, *alpha_hi, &t1, &t2); - pix_multiply_2x128 (dst_lo, dst_hi, &t1, &t2, dst_lo, dst_hi); + pix_multiply_2x128(dst_lo, dst_hi, &t1, &t2, dst_lo, dst_hi); - *dst_lo = _mm_adds_epu8 (*src_lo, *dst_lo); - *dst_hi = _mm_adds_epu8 (*src_hi, *dst_hi); + *dst_lo = _mm_adds_epu8(*src_lo, *dst_lo); + *dst_hi = _mm_adds_epu8(*src_hi, *dst_hi); } -static force_inline uint32_t -core_combine_over_u_pixel_sse2 (uint32_t src, uint32_t dst) +static force_inline uint32_t core_combine_over_u_pixel_sse2(uint32_t src, + uint32_t dst) { uint8_t a; __m128i xmms; a = src >> 24; - if (a == 0xff) - { - return src; - } - else if (src) - { - xmms = unpack_32_1x128 (src); - return pack_1x128_32 ( - over_1x128 (xmms, expand_alpha_1x128 (xmms), - unpack_32_1x128 (dst))); + if (a == 0xff) { + return src; + } else if (src) { + xmms = unpack_32_1x128(src); + return pack_1x128_32( + over_1x128(xmms, expand_alpha_1x128(xmms), unpack_32_1x128(dst))); } return dst; } -//static force_inline void -//core_combine_over_u_sse2_no_mask (uint32_t * pd, +// static force_inline void +// core_combine_over_u_sse2_no_mask (uint32_t * pd, // const uint32_t* ps, // int w) -void comp_func_SourceOver_sse2(uint32_t *pd, const uint32_t *ps, int w, uint32_t) +void comp_func_SourceOver_sse2(uint32_t* pd, const uint32_t* ps, int w, + uint32_t) { uint32_t s, d; /* Align dst on a 16-byte boundary */ - while (w && ((uintptr_t)pd & 15)) - { - d = *pd; - s = *ps; - - if (s) - *pd = core_combine_over_u_pixel_sse2 (s, d); - pd++; - ps++; - w--; + while (w && ((uintptr_t)pd & 15)) { + d = *pd; + s = *ps; + + if (s) *pd = core_combine_over_u_pixel_sse2(s, d); + pd++; + ps++; + w--; } - while (w >= 4) - { - __m128i src; - __m128i src_hi, src_lo, dst_hi, dst_lo; - __m128i alpha_hi, alpha_lo; + while (w >= 4) { + __m128i src; + __m128i src_hi, src_lo, dst_hi, dst_lo; + __m128i alpha_hi, alpha_lo; - src = load_128_unaligned ((__m128i *)ps); + src = load_128_unaligned((__m128i*)ps); - if (!is_zero (src)) - { - if (is_opaque (src)) - { - save_128_aligned ((__m128i *)pd, src); - } - else - { - __m128i dst = load_128_aligned ((__m128i *)pd); + if (!is_zero(src)) { + if (is_opaque(src)) { + save_128_aligned((__m128i*)pd, src); + } else { + __m128i dst = load_128_aligned((__m128i*)pd); - unpack_128_2x128 (src, &src_lo, &src_hi); - unpack_128_2x128 (dst, &dst_lo, &dst_hi); + unpack_128_2x128(src, &src_lo, &src_hi); + unpack_128_2x128(dst, &dst_lo, &dst_hi); - expand_alpha_2x128 (src_lo, src_hi, - &alpha_lo, &alpha_hi); - over_2x128 (&src_lo, &src_hi, &alpha_lo, &alpha_hi, - &dst_lo, &dst_hi); + expand_alpha_2x128(src_lo, src_hi, &alpha_lo, &alpha_hi); + over_2x128(&src_lo, &src_hi, &alpha_lo, &alpha_hi, &dst_lo, + &dst_hi); - save_128_aligned ( - (__m128i *)pd, - pack_2x128_128 (dst_lo, dst_hi)); + save_128_aligned((__m128i*)pd, pack_2x128_128(dst_lo, dst_hi)); + } } - } - ps += 4; - pd += 4; - w -= 4; + ps += 4; + pd += 4; + w -= 4; } - while (w) - { - d = *pd; - s = *ps; + while (w) { + d = *pd; + s = *ps; - if (s) - *pd = core_combine_over_u_pixel_sse2 (s, d); - pd++; - ps++; + if (s) *pd = core_combine_over_u_pixel_sse2(s, d); + pd++; + ps++; - w--; + w--; } } - #endif diff --git a/src/vector/velapsedtimer.cpp b/src/vector/velapsedtimer.cpp index e4d516c..59cdced 100644 --- a/src/vector/velapsedtimer.cpp +++ b/src/vector/velapsedtimer.cpp @@ -1,4 +1,4 @@ -#include"velapsedtimer.h" +#include "velapsedtimer.h" void VElapsedTimer::start() { @@ -16,14 +16,14 @@ double VElapsedTimer::restart() double VElapsedTimer::elapsed() const { if (!isValid()) return 0; - return std::chrono::duration(std::chrono::high_resolution_clock::now()-clock).count(); + return std::chrono::duration( + std::chrono::high_resolution_clock::now() - clock) + .count(); } bool VElapsedTimer::hasExpired(double time) { double elapsedTime = elapsed(); - if (elapsedTime > time) - return true; + if (elapsedTime > time) return true; return false; } - diff --git a/src/vector/velapsedtimer.h b/src/vector/velapsedtimer.h index 070c7d8..f8d2f9a 100644 --- a/src/vector/velapsedtimer.h +++ b/src/vector/velapsedtimer.h @@ -1,20 +1,20 @@ #ifndef VELAPSEDTIMER_H #define VELAPSEDTIMER_H +#include #include "vglobal.h" -#include -class VElapsedTimer -{ +class VElapsedTimer { public: - VElapsedTimer():m_valid(false){} - double elapsed() const; - bool hasExpired(double millsec); - void start(); - double restart(); - inline bool isValid() const {return m_valid;} + VElapsedTimer() : m_valid(false) {} + double elapsed() const; + bool hasExpired(double millsec); + void start(); + double restart(); + inline bool isValid() const { return m_valid; } + private: std::chrono::high_resolution_clock::time_point clock; - bool m_valid; + bool m_valid; }; -#endif // VELAPSEDTIMER_H +#endif // VELAPSEDTIMER_H diff --git a/src/vector/vglobal.h b/src/vector/vglobal.h index 0585955..df6ae1d 100644 --- a/src/vector/vglobal.h +++ b/src/vector/vglobal.h @@ -1,59 +1,59 @@ #ifndef VGLOBAL_H #define VGLOBAL_H -#include #include -#include -#include -#include - -typedef uint32_t uint; -typedef uint16_t ushort; -typedef uint8_t uchar; +#include +#include +#include +#include +typedef uint32_t uint; +typedef uint16_t ushort; +typedef uint8_t uchar; #if !defined(V_NAMESPACE) -# define V_USE_NAMESPACE -# define V_BEGIN_NAMESPACE -# define V_END_NAMESPACE +#define V_USE_NAMESPACE +#define V_BEGIN_NAMESPACE +#define V_END_NAMESPACE #else /* user namespace */ -# define V_USE_NAMESPACE using namespace ::V_NAMESPACE; -# define V_BEGIN_NAMESPACE namespace V_NAMESPACE { -# define V_END_NAMESPACE } +#define V_USE_NAMESPACE using namespace ::V_NAMESPACE; +#define V_BEGIN_NAMESPACE namespace V_NAMESPACE { +#define V_END_NAMESPACE } #endif #define V_UNUSED __attribute__((__unused__)) -#define V_REQUIRED_RESULT __attribute__ ((__warn_unused_result__)) +#define V_REQUIRED_RESULT __attribute__((__warn_unused_result__)) #define V_CONSTEXPR constexpr -#define V_NOTHROW noexcept +#define V_NOTHROW noexcept -#include"vdebug.h" +#include "vdebug.h" #define VECTOR_FALLTHROUGH -#include -class RefCount -{ +#include +class RefCount { public: - inline RefCount(int i):atomic(i){} - inline bool ref() { + inline RefCount(int i) : atomic(i) {} + inline bool ref() + { int count = atomic.load(); - if (count == 0) // !isSharable + if (count == 0) // !isSharable return false; - if (count != -1) // !isStatic + if (count != -1) // !isStatic atomic.fetch_add(1); return true; } - inline bool deref() { + inline bool deref() + { int count = atomic.load(); - if (count == 0) // !isSharable + if (count == 0) // !isSharable return false; - if (count == -1) // isStatic + if (count == -1) // isStatic return true; atomic.fetch_sub(1); return --count; @@ -69,21 +69,26 @@ public: int count = atomic.load(); return count == -1; } - inline int count()const{return atomic;} - void setOwned() { atomic.store(1); } + inline int count() const { return atomic; } + void setOwned() { atomic.store(1); } + private: std::atomic atomic; }; template -V_CONSTEXPR inline const T &vMin(const T &a, const T &b) { return (a < b) ? a : b; } +V_CONSTEXPR inline const T &vMin(const T &a, const T &b) +{ + return (a < b) ? a : b; +} template -V_CONSTEXPR inline const T &vMax(const T &a, const T &b) { return (a < b) ? b : a; } - - +V_CONSTEXPR inline const T &vMax(const T &a, const T &b) +{ + return (a < b) ? b : a; +} static const double EPSILON_DOUBLE = 0.000000000001f; -static const float EPSILON_FLOAT = 0.000001f; +static const float EPSILON_FLOAT = 0.000001f; static inline bool vCompare(double p1, double p2) { @@ -108,21 +113,20 @@ static inline bool vIsZero(double f) // Approximate sqrt(x*x + y*y) using the alpha max plus beta min algorithm. // This uses alpha = 1, beta = 3/8, which results in a maximum error of less // than 7% compared to the correct value. -static inline float -vLineLength(float x1, float y1, float x2, float y2) +static inline float vLineLength(float x1, float y1, float x2, float y2) { - float x = x2 - x1; - float y = y2 - y1; + float x = x2 - x1; + float y = y2 - y1; - x = x < 0 ? -x : x; - y = y < 0 ? -y : y; + x = x < 0 ? -x : x; + y = y < 0 ? -y : y; - return (x > y ? x + 0.375 * y : y + 0.375 * x); + return (x > y ? x + 0.375 * y : y + 0.375 * x); } -class vFlagHelper -{ +class vFlagHelper { int i; + public: constexpr inline vFlagHelper(int ai) noexcept : i(ai) {} constexpr inline operator int() const noexcept { return i; } @@ -133,19 +137,18 @@ public: constexpr inline operator uint() const noexcept { return uint(i); } }; -template -class vFlag -{ +template +class vFlag { public: - static_assert((sizeof(Enum) <= sizeof(int)), - "vFlag only supports int as storage so bigger type will overflow"); - static_assert((std::is_enum::value), "vFlag is only usable on enumeration types."); + static_assert( + (sizeof(Enum) <= sizeof(int)), + "vFlag only supports int as storage so bigger type will overflow"); + static_assert((std::is_enum::value), + "vFlag is only usable on enumeration types."); typedef typename std::conditional< - std::is_unsigned::type>::value, - unsigned int, - signed int - >::type Int; + std::is_unsigned::type>::value, + unsigned int, signed int>::type Int; typedef Enum enum_type; // compiler-generated copy/move ctor/assignment operators are fine! @@ -154,28 +157,83 @@ public: constexpr inline vFlag() noexcept : i(0) {} constexpr inline vFlag(vFlagHelper f) noexcept : i(f) {} - inline vFlag &operator&=(int mask) noexcept { i &= mask; return *this; } - inline vFlag &operator&=(uint mask) noexcept { i &= mask; return *this; } - inline vFlag &operator&=(Enum mask) noexcept { i &= Int(mask); return *this; } - inline vFlag &operator|=(vFlag f) noexcept { i |= f.i; return *this; } - inline vFlag &operator|=(Enum f) noexcept { i |= Int(f); return *this; } - inline vFlag &operator^=(vFlag f) noexcept { i ^= f.i; return *this; } - inline vFlag &operator^=(Enum f) noexcept { i ^= Int(f); return *this; } + inline vFlag &operator&=(int mask) noexcept + { + i &= mask; + return *this; + } + inline vFlag &operator&=(uint mask) noexcept + { + i &= mask; + return *this; + } + inline vFlag &operator&=(Enum mask) noexcept + { + i &= Int(mask); + return *this; + } + inline vFlag &operator|=(vFlag f) noexcept + { + i |= f.i; + return *this; + } + inline vFlag &operator|=(Enum f) noexcept + { + i |= Int(f); + return *this; + } + inline vFlag &operator^=(vFlag f) noexcept + { + i ^= f.i; + return *this; + } + inline vFlag &operator^=(Enum f) noexcept + { + i ^= Int(f); + return *this; + } constexpr inline operator Int() const noexcept { return i; } - constexpr inline vFlag operator|(vFlag f) const { return vFlag(vFlagHelper(i | f.i)); } - constexpr inline vFlag operator|(Enum f) const noexcept { return vFlag(vFlagHelper(i | Int(f))); } - constexpr inline vFlag operator^(vFlag f) const noexcept { return vFlag(vFlagHelper(i ^ f.i)); } - constexpr inline vFlag operator^(Enum f) const noexcept { return vFlag(vFlagHelper(i ^ Int(f))); } - constexpr inline vFlag operator&(int mask) const noexcept { return vFlag(vFlagHelper(i & mask)); } - constexpr inline vFlag operator&(uint mask) const noexcept { return vFlag(vFlagHelper(i & mask)); } - constexpr inline vFlag operator&(Enum f) const noexcept { return vFlag(vFlagHelper(i & Int(f))); } - constexpr inline vFlag operator~() const noexcept { return vFlag(vFlagHelper(~i)); } + constexpr inline vFlag operator|(vFlag f) const + { + return vFlag(vFlagHelper(i | f.i)); + } + constexpr inline vFlag operator|(Enum f) const noexcept + { + return vFlag(vFlagHelper(i | Int(f))); + } + constexpr inline vFlag operator^(vFlag f) const noexcept + { + return vFlag(vFlagHelper(i ^ f.i)); + } + constexpr inline vFlag operator^(Enum f) const noexcept + { + return vFlag(vFlagHelper(i ^ Int(f))); + } + constexpr inline vFlag operator&(int mask) const noexcept + { + return vFlag(vFlagHelper(i & mask)); + } + constexpr inline vFlag operator&(uint mask) const noexcept + { + return vFlag(vFlagHelper(i & mask)); + } + constexpr inline vFlag operator&(Enum f) const noexcept + { + return vFlag(vFlagHelper(i & Int(f))); + } + constexpr inline vFlag operator~() const noexcept + { + return vFlag(vFlagHelper(~i)); + } constexpr inline bool operator!() const noexcept { return !i; } - constexpr inline bool testFlag(Enum f) const noexcept { return (i & Int(f)) == Int(f) && (Int(f) != 0 || i == Int(f) ); } + constexpr inline bool testFlag(Enum f) const noexcept + { + return (i & Int(f)) == Int(f) && (Int(f) != 0 || i == Int(f)); + } inline vFlag &setFlag(Enum f, bool on = true) noexcept { return on ? (*this |= f) : (*this &= ~f); @@ -184,28 +242,37 @@ public: Int i; }; - -class VColor -{ +class VColor { public: - inline VColor() noexcept {a = r = g = b = 0;} - inline VColor(int red, int green, int blue, int alpha = 255) noexcept { r = red; g = green; b = blue; a = alpha; } - inline int red() const noexcept {return r;} - inline int green() const noexcept{return g;} - inline int blue() const noexcept{return b;} - inline int alpha() const noexcept{return a;} - inline void setRed(int red) noexcept {r = red;} - inline void setGreen(int green)noexcept {g = green;} - inline void setBlue(int blue)noexcept {b = blue;} - inline void setAlpha(int alpha)noexcept {a = alpha;} - inline bool isOpaque() const{return a == 255;} - inline bool operator==(const VColor &o) const { return ((a==o.a) && (r==o.r) && (g == o.g) && (b == o.b));} - uint premulARGB() const { - int pr= (r * a)/255; - int pg= (g * a)/255; - int pb= (b * a)/255; - return uint((a<<24) | (pr<<16) | (pg<<8) | (pb)); + inline VColor() noexcept { a = r = g = b = 0; } + inline VColor(int red, int green, int blue, int alpha = 255) noexcept + { + r = red; + g = green; + b = blue; + a = alpha; + } + inline int red() const noexcept { return r; } + inline int green() const noexcept { return g; } + inline int blue() const noexcept { return b; } + inline int alpha() const noexcept { return a; } + inline void setRed(int red) noexcept { r = red; } + inline void setGreen(int green) noexcept { g = green; } + inline void setBlue(int blue) noexcept { b = blue; } + inline void setAlpha(int alpha) noexcept { a = alpha; } + inline bool isOpaque() const { return a == 255; } + inline bool operator==(const VColor &o) const + { + return ((a == o.a) && (r == o.r) && (g == o.g) && (b == o.b)); } + uint premulARGB() const + { + int pr = (r * a) / 255; + int pg = (g * a) / 255; + int pb = (b * a) / 255; + return uint((a << 24) | (pr << 16) | (pg << 8) | (pb)); + } + public: ushort a; ushort r; @@ -213,32 +280,20 @@ public: ushort b; }; -enum class FillRule { - EvenOdd, - Winding -}; - -enum class JoinStyle { - Miter, - Bevel, - Round -}; -enum class CapStyle { - Flat, - Square, - Round -}; +enum class FillRule { EvenOdd, Winding }; +enum class JoinStyle { Miter, Bevel, Round }; +enum class CapStyle { Flat, Square, Round }; #ifndef V_CONSTRUCTOR_FUNCTION -# define V_CONSTRUCTOR_FUNCTION0(AFUNC) \ - namespace { \ - static const struct AFUNC ## _ctor_class_ { \ - inline AFUNC ## _ctor_class_() { AFUNC(); } \ - } AFUNC ## _ctor_instance_; \ +#define V_CONSTRUCTOR_FUNCTION0(AFUNC) \ + namespace { \ + static const struct AFUNC##_ctor_class_ { \ + inline AFUNC##_ctor_class_() { AFUNC(); } \ + } AFUNC##_ctor_instance_; \ } -# define V_CONSTRUCTOR_FUNCTION(AFUNC) V_CONSTRUCTOR_FUNCTION0(AFUNC) +#define V_CONSTRUCTOR_FUNCTION(AFUNC) V_CONSTRUCTOR_FUNCTION0(AFUNC) #endif -#endif //VGLOBAL_H +#endif // VGLOBAL_H diff --git a/src/vector/vinterpolator.cpp b/src/vector/vinterpolator.cpp index 90f0936..58c2d14 100644 --- a/src/vector/vinterpolator.cpp +++ b/src/vector/vinterpolator.cpp @@ -1,134 +1,118 @@ -#include"vinterpolator.h" -#include +#include "vinterpolator.h" +#include V_BEGIN_NAMESPACE -#define NEWTON_ITERATIONS 4 -#define NEWTON_MIN_SLOPE 0.02 -#define SUBDIVISION_PRECISION 0.0000001 +#define NEWTON_ITERATIONS 4 +#define NEWTON_MIN_SLOPE 0.02 +#define SUBDIVISION_PRECISION 0.0000001 #define SUBDIVISION_MAX_ITERATIONS 10 const float VInterpolator::kSampleStepSize = - 1.0 / float(VInterpolator::kSplineTableSize - 1); + 1.0 / float(VInterpolator::kSplineTableSize - 1); -void -VInterpolator::init(float aX1, float aY1, float aX2, float aY2) +void VInterpolator::init(float aX1, float aY1, float aX2, float aY2) { mX1 = aX1; mY1 = aY1; mX2 = aX2; mY2 = aY2; - if (mX1 != mY1 || mX2 != mY2) - CalcSampleValues(); + if (mX1 != mY1 || mX2 != mY2) CalcSampleValues(); } -/*static*/ float -VInterpolator::CalcBezier(float aT, - float aA1, - float aA2) +/*static*/ float VInterpolator::CalcBezier(float aT, float aA1, float aA2) { - // use Horner's scheme to evaluate the Bezier polynomial - return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT; + // use Horner's scheme to evaluate the Bezier polynomial + return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; } -void -VInterpolator::CalcSampleValues() +void VInterpolator::CalcSampleValues() { for (int i = 0; i < kSplineTableSize; ++i) { mSampleValues[i] = CalcBezier(float(i) * kSampleStepSize, mX1, mX2); } } -float -VInterpolator::GetSlope(float aT, - float aA1, - float aA2) +float VInterpolator::GetSlope(float aT, float aA1, float aA2) { - return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1); + return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); } - -float -VInterpolator::value(float aX) const +float VInterpolator::value(float aX) const { - if (mX1 == mY1 && mX2 == mY2) - return aX; + if (mX1 == mY1 && mX2 == mY2) return aX; - return CalcBezier(GetTForX(aX), mY1, mY2); + return CalcBezier(GetTForX(aX), mY1, mY2); } -float -VInterpolator::GetTForX(float aX) const +float VInterpolator::GetTForX(float aX) const { - // Find interval where t lies - float intervalStart = 0.0; - const float* currentSample = &mSampleValues[1]; - const float* const lastSample = &mSampleValues[kSplineTableSize - 1]; - for (; currentSample != lastSample && *currentSample <= aX; - ++currentSample) { - intervalStart += kSampleStepSize; - } - --currentSample; // t now lies between *currentSample and *currentSample+1 - - // Interpolate to provide an initial guess for t - float dist = (aX - *currentSample) / - (*(currentSample+1) - *currentSample); - float guessForT = intervalStart + dist * kSampleStepSize; - - // Check the slope to see what strategy to use. If the slope is too small - // Newton-Raphson iteration won't converge on a root so we use bisection - // instead. - float initialSlope = GetSlope(guessForT, mX1, mX2); - if (initialSlope >= NEWTON_MIN_SLOPE) { - return NewtonRaphsonIterate(aX, guessForT); - } else if (initialSlope == 0.0) { - return guessForT; - } else { - return BinarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize); - } + // Find interval where t lies + float intervalStart = 0.0; + const float* currentSample = &mSampleValues[1]; + const float* const lastSample = &mSampleValues[kSplineTableSize - 1]; + for (; currentSample != lastSample && *currentSample <= aX; + ++currentSample) { + intervalStart += kSampleStepSize; + } + --currentSample; // t now lies between *currentSample and *currentSample+1 + + // Interpolate to provide an initial guess for t + float dist = + (aX - *currentSample) / (*(currentSample + 1) - *currentSample); + float guessForT = intervalStart + dist * kSampleStepSize; + + // Check the slope to see what strategy to use. If the slope is too small + // Newton-Raphson iteration won't converge on a root so we use bisection + // instead. + float initialSlope = GetSlope(guessForT, mX1, mX2); + if (initialSlope >= NEWTON_MIN_SLOPE) { + return NewtonRaphsonIterate(aX, guessForT); + } else if (initialSlope == 0.0) { + return guessForT; + } else { + return BinarySubdivide(aX, intervalStart, + intervalStart + kSampleStepSize); + } } -float -VInterpolator::NewtonRaphsonIterate(float aX, float aGuessT) const +float VInterpolator::NewtonRaphsonIterate(float aX, float aGuessT) const { - // Refine guess with Newton-Raphson iteration - for (int i = 0; i < NEWTON_ITERATIONS; ++i) { - // We're trying to find where f(t) = aX, - // so we're actually looking for a root for: CalcBezier(t) - aX - float currentX = CalcBezier(aGuessT, mX1, mX2) - aX; - float currentSlope = GetSlope(aGuessT, mX1, mX2); + // Refine guess with Newton-Raphson iteration + for (int i = 0; i < NEWTON_ITERATIONS; ++i) { + // We're trying to find where f(t) = aX, + // so we're actually looking for a root for: CalcBezier(t) - aX + float currentX = CalcBezier(aGuessT, mX1, mX2) - aX; + float currentSlope = GetSlope(aGuessT, mX1, mX2); - if (currentSlope == 0.0) - return aGuessT; + if (currentSlope == 0.0) return aGuessT; - aGuessT -= currentX / currentSlope; - } + aGuessT -= currentX / currentSlope; + } - return aGuessT; + return aGuessT; } -float -VInterpolator::BinarySubdivide(float aX, float aA, float aB) const +float VInterpolator::BinarySubdivide(float aX, float aA, float aB) const { - float currentX; - float currentT; - int i = 0; - - do - { - currentT = aA + (aB - aA) / 2.0; - currentX = CalcBezier(currentT, mX1, mX2) - aX; - - if (currentX > 0.0) { - aB = currentT; - } else { - aA = currentT; - } - } while (fabs(currentX) > SUBDIVISION_PRECISION - && ++i < SUBDIVISION_MAX_ITERATIONS); - - return currentT; + float currentX; + float currentT; + int i = 0; + + do { + currentT = aA + (aB - aA) / 2.0; + currentX = CalcBezier(currentT, mX1, mX2) - aX; + + if (currentX > 0.0) { + aB = currentT; + } else { + aA = currentT; + } + } while (fabs(currentX) > SUBDIVISION_PRECISION && + ++i < SUBDIVISION_MAX_ITERATIONS); + + return currentT; } V_END_NAMESPACE diff --git a/src/vector/vinterpolator.h b/src/vector/vinterpolator.h index f609d0c..0d3b60e 100644 --- a/src/vector/vinterpolator.h +++ b/src/vector/vinterpolator.h @@ -5,80 +5,62 @@ V_BEGIN_NAMESPACE -class VInterpolator -{ +class VInterpolator { public: - VInterpolator() { /* caller must call Init later */ } + VInterpolator() + { /* caller must call Init later */ + } - VInterpolator(float aX1, float aY1, - float aX2, float aY2) + VInterpolator(float aX1, float aY1, float aX2, float aY2) { - init(aX1, aY1, aX2, aY2); + init(aX1, aY1, aX2, aY2); } VInterpolator(VPointF pt1, VPointF pt2) { - init(pt1.x(), pt1.y(), pt2.x(), pt2.y()); + init(pt1.x(), pt1.y(), pt2.x(), pt2.y()); } - void init(float aX1, float aY1, - float aX2, float aY2); + void init(float aX1, float aY1, float aX2, float aY2); float value(float aX) const; void GetSplineDerivativeValues(float aX, float& aDX, float& aDY) const; + private: - void - CalcSampleValues(); - - /** - * Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2. - */ - static float - CalcBezier(float aT, float aA1, float aA2); - - /** - * Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2. - */ - static float - GetSlope(float aT, float aA1, float aA2); - - float - GetTForX(float aX) const; - - float - NewtonRaphsonIterate(float aX, float aGuessT) const; - - float - BinarySubdivide(float aX, float aA, float aB) const; - - static float - A(float aA1, float aA2) - { - return 1.0 - 3.0 * aA2 + 3.0 * aA1; - } - - static float - B(float aA1, float aA2) - { - return 3.0 * aA2 - 6.0 * aA1; - } - - static float - C(float aA1) - { - return 3.0 * aA1; - } + void CalcSampleValues(); + + /** + * Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2. + */ + static float CalcBezier(float aT, float aA1, float aA2); + + /** + * Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2. + */ + static float GetSlope(float aT, float aA1, float aA2); + + float GetTForX(float aX) const; + + float NewtonRaphsonIterate(float aX, float aGuessT) const; + + float BinarySubdivide(float aX, float aA, float aB) const; + + static float A(float aA1, float aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; } + + static float B(float aA1, float aA2) { return 3.0 * aA2 - 6.0 * aA1; } + + static float C(float aA1) { return 3.0 * aA1; } float mX1; float mY1; float mX2; float mY2; enum { kSplineTableSize = 11 }; - float mSampleValues[kSplineTableSize]; + float mSampleValues[kSplineTableSize]; static const float kSampleStepSize; }; V_END_NAMESPACE -#endif // VINTERPOLATOR_H +#endif // VINTERPOLATOR_H diff --git a/src/vector/vmatrix.cpp b/src/vector/vmatrix.cpp index 688b273..5fff287 100644 --- a/src/vector/vmatrix.cpp +++ b/src/vector/vmatrix.cpp @@ -1,8 +1,8 @@ -#include"vmatrix.h" -#include -#include -#include -#include +#include "vmatrix.h" +#include +#include +#include +#include V_BEGIN_NAMESPACE @@ -13,8 +13,8 @@ V_BEGIN_NAMESPACE inline float VMatrix::determinant() const { - return m11*(m33*m22 - mty*m23) - - m21*(m33*m12 - mty*m13)+mtx*(m23*m12 - m22*m13); + return m11 * (m33 * m22 - mty * m23) - m21 * (m33 * m12 - mty * m13) + + mtx * (m23 * m12 - m22 * m13); } bool VMatrix::isAffine() const @@ -48,8 +48,7 @@ bool VMatrix::isTranslating() const VMatrix &VMatrix::operator*=(float num) { - if (num == 1.) - return *this; + if (num == 1.) return *this; m11 *= num; m12 *= num; @@ -60,31 +59,28 @@ VMatrix &VMatrix::operator*=(float num) mtx *= num; mty *= num; m33 *= num; - if (dirty < MatrixType::Scale) - dirty = MatrixType::Scale; + if (dirty < MatrixType::Scale) dirty = MatrixType::Scale; return *this; } VMatrix &VMatrix::operator/=(float div) { - if (div == 0) - return *this; + if (div == 0) return *this; - div = 1/div; + div = 1 / div; return operator*=(div); } VMatrix::MatrixType VMatrix::type() const { - if(dirty == MatrixType::None || dirty < mType) - return mType; + if (dirty == MatrixType::None || dirty < mType) return mType; switch (dirty) { case MatrixType::Project: if (!vIsZero(m13) || !vIsZero(m23) || !vIsZero(m33 - 1)) { - mType = MatrixType::Project; - break; + mType = MatrixType::Project; + break; } case MatrixType::Shear: case MatrixType::Rotate: @@ -115,13 +111,11 @@ VMatrix::MatrixType VMatrix::type() const return mType; } - VMatrix &VMatrix::translate(float dx, float dy) { - if (dx == 0 && dy == 0) - return *this; + if (dx == 0 && dy == 0) return *this; - switch(type()) { + switch (type()) { case MatrixType::None: mtx = dx; mty = dy; @@ -131,28 +125,26 @@ VMatrix &VMatrix::translate(float dx, float dy) mty += dy; break; case MatrixType::Scale: - mtx += dx* m11; - mty += dy* m22; + mtx += dx * m11; + mty += dy * m22; break; case MatrixType::Project: m33 += dx * m13 + dy * m23; case MatrixType::Shear: case MatrixType::Rotate: - mtx += dx*m11 + dy*m21; - mty += dy*m22 + dx*m12; + mtx += dx * m11 + dy * m21; + mty += dy * m22 + dx * m12; break; } - if (dirty < MatrixType::Translate) - dirty = MatrixType::Translate; + if (dirty < MatrixType::Translate) dirty = MatrixType::Translate; return *this; } -VMatrix & VMatrix::scale(float sx, float sy) +VMatrix &VMatrix::scale(float sx, float sy) { - if (sx == 1 && sy == 1) - return *this; + if (sx == 1 && sy == 1) return *this; - switch(type()) { + switch (type()) { case MatrixType::None: case MatrixType::Translate: m11 = sx; @@ -170,56 +162,53 @@ VMatrix & VMatrix::scale(float sx, float sy) m22 *= sy; break; } - if (dirty < MatrixType::Scale) - dirty = MatrixType::Scale; + if (dirty < MatrixType::Scale) dirty = MatrixType::Scale; return *this; } -VMatrix & VMatrix::shear(float sh, float sv) +VMatrix &VMatrix::shear(float sh, float sv) { - if (sh == 0 && sv == 0) - return *this; + if (sh == 0 && sv == 0) return *this; - switch(type()) { + switch (type()) { case MatrixType::None: case MatrixType::Translate: m12 = sv; m21 = sh; break; case MatrixType::Scale: - m12 = sv*m22; - m21 = sh*m11; + m12 = sv * m22; + m21 = sh * m11; break; case MatrixType::Project: { - float tm13 = sv*m23; - float tm23 = sh*m13; + float tm13 = sv * m23; + float tm23 = sh * m13; m13 += tm13; m23 += tm23; } case MatrixType::Rotate: case MatrixType::Shear: { - float tm11 = sv*m21; - float tm22 = sh*m12; - float tm12 = sv*m22; - float tm21 = sh*m11; - m11 += tm11; m12 += tm12; - m21 += tm21; m22 += tm22; + float tm11 = sv * m21; + float tm22 = sh * m12; + float tm12 = sv * m22; + float tm21 = sh * m11; + m11 += tm11; + m12 += tm12; + m21 += tm21; + m22 += tm22; break; } } - if (dirty < MatrixType::Shear) - dirty = MatrixType::Shear; + if (dirty < MatrixType::Shear) dirty = MatrixType::Shear; return *this; } - static const float deg2rad = float(0.017453292519943295769); // pi/180 static const float inv_dist_to_plane = 1. / 1024.; -VMatrix & VMatrix::rotate(float a, Axis axis) +VMatrix &VMatrix::rotate(float a, Axis axis) { - if (a == 0) - return *this; + if (a == 0) return *this; float sina = 0; float cosa = 0; @@ -229,14 +218,14 @@ VMatrix & VMatrix::rotate(float a, Axis axis) sina = -1.; else if (a == 180.) cosa = -1.; - else{ - float b = deg2rad*a; // convert to radians - sina = std::sin(b); // fast and convenient + else { + float b = deg2rad * a; // convert to radians + sina = std::sin(b); // fast and convenient cosa = std::cos(b); } if (axis == Axis::Z) { - switch(type()) { + switch (type()) { case MatrixType::None: case MatrixType::Translate: m11 = cosa; @@ -245,33 +234,36 @@ VMatrix & VMatrix::rotate(float a, Axis axis) m22 = cosa; break; case MatrixType::Scale: { - float tm11 = cosa*m11; - float tm12 = sina*m22; - float tm21 = -sina*m11; - float tm22 = cosa*m22; - m11 = tm11; m12 = tm12; - m21 = tm21; m22 = tm22; + float tm11 = cosa * m11; + float tm12 = sina * m22; + float tm21 = -sina * m11; + float tm22 = cosa * m22; + m11 = tm11; + m12 = tm12; + m21 = tm21; + m22 = tm22; break; } case MatrixType::Project: { - float tm13 = cosa*m13 + sina*m23; - float tm23 = -sina*m13 + cosa*m23; + float tm13 = cosa * m13 + sina * m23; + float tm23 = -sina * m13 + cosa * m23; m13 = tm13; m23 = tm23; } case MatrixType::Rotate: case MatrixType::Shear: { - float tm11 = cosa*m11 + sina*m21; - float tm12 = cosa*m12 + sina*m22; - float tm21 = -sina*m11 + cosa*m21; - float tm22 = -sina*m12 + cosa*m22; - m11 = tm11; m12 = tm12; - m21 = tm21; m22 = tm22; + float tm11 = cosa * m11 + sina * m21; + float tm12 = cosa * m12 + sina * m22; + float tm21 = -sina * m11 + cosa * m21; + float tm22 = -sina * m12 + cosa * m22; + m11 = tm11; + m12 = tm12; + m21 = tm21; + m22 = tm22; break; } } - if (dirty < MatrixType::Rotate) - dirty = MatrixType::Rotate; + if (dirty < MatrixType::Rotate) dirty = MatrixType::Rotate; } else { VMatrix result; if (axis == Axis::Y) { @@ -291,69 +283,74 @@ VMatrix & VMatrix::rotate(float a, Axis axis) VMatrix VMatrix::operator*(const VMatrix &m) const { const MatrixType otherType = m.type(); - if (otherType == MatrixType::None) - return *this; + if (otherType == MatrixType::None) return *this; const MatrixType thisType = type(); - if (thisType == MatrixType::None) - return m; + if (thisType == MatrixType::None) return m; - VMatrix t; + VMatrix t; MatrixType type = vMax(thisType, otherType); - switch(type) { + switch (type) { case MatrixType::None: break; case MatrixType::Translate: t.mtx = mtx + m.mtx; t.mty += mty + m.mty; break; - case MatrixType::Scale: - { - float m11v = m11*m.m11; - float m22v = m22*m.m22; + case MatrixType::Scale: { + float m11v = m11 * m.m11; + float m22v = m22 * m.m22; - float m31v = mtx*m.m11 + m.mtx; - float m32v = mty*m.m22 + m.mty; + float m31v = mtx * m.m11 + m.mtx; + float m32v = mty * m.m22 + m.mty; t.m11 = m11v; t.m22 = m22v; - t.mtx = m31v; t.mty = m32v; + t.mtx = m31v; + t.mty = m32v; break; } case MatrixType::Rotate: - case MatrixType::Shear: - { - float m11v = m11*m.m11 + m12*m.m21; - float m12v = m11*m.m12 + m12*m.m22; + case MatrixType::Shear: { + float m11v = m11 * m.m11 + m12 * m.m21; + float m12v = m11 * m.m12 + m12 * m.m22; - float m21v = m21*m.m11 + m22*m.m21; - float m22v = m21*m.m12 + m22*m.m22; + float m21v = m21 * m.m11 + m22 * m.m21; + float m22v = m21 * m.m12 + m22 * m.m22; - float m31v = mtx*m.m11 + mty*m.m21 + m.mtx; - float m32v = mtx*m.m12 + mty*m.m22 + m.mty; + float m31v = mtx * m.m11 + mty * m.m21 + m.mtx; + float m32v = mtx * m.m12 + mty * m.m22 + m.mty; - t.m11 = m11v; t.m12 = m12v; - t.m21 = m21v; t.m22 = m22v; - t.mtx = m31v; t.mty = m32v; + t.m11 = m11v; + t.m12 = m12v; + t.m21 = m21v; + t.m22 = m22v; + t.mtx = m31v; + t.mty = m32v; break; } - case MatrixType::Project: - { - float m11v = m11*m.m11 + m12*m.m21 + m13*m.mtx; - float m12v = m11*m.m12 + m12*m.m22 + m13*m.mty; - float m13v = m11*m.m13 + m12*m.m23 + m13*m.m33; - - float m21v = m21*m.m11 + m22*m.m21 + m23*m.mtx; - float m22v = m21*m.m12 + m22*m.m22 + m23*m.mty; - float m23v = m21*m.m13 + m22*m.m23 + m23*m.m33; - - float m31v = mtx*m.m11 + mty*m.m21 + m33*m.mtx; - float m32v = mtx*m.m12 + mty*m.m22 + m33*m.mty; - float m33v = mtx*m.m13 + mty*m.m23 + m33*m.m33; - - t.m11 = m11v; t.m12 = m12v; t.m13 = m13v; - t.m21 = m21v; t.m22 = m22v; t.m23 = m23v; - t.mtx = m31v; t.mty = m32v; t.m33 = m33v; + case MatrixType::Project: { + float m11v = m11 * m.m11 + m12 * m.m21 + m13 * m.mtx; + float m12v = m11 * m.m12 + m12 * m.m22 + m13 * m.mty; + float m13v = m11 * m.m13 + m12 * m.m23 + m13 * m.m33; + + float m21v = m21 * m.m11 + m22 * m.m21 + m23 * m.mtx; + float m22v = m21 * m.m12 + m22 * m.m22 + m23 * m.mty; + float m23v = m21 * m.m13 + m22 * m.m23 + m23 * m.m33; + + float m31v = mtx * m.m11 + mty * m.m21 + m33 * m.mtx; + float m32v = mtx * m.m12 + mty * m.m22 + m33 * m.mty; + float m33v = mtx * m.m13 + mty * m.m23 + m33 * m.m33; + + t.m11 = m11v; + t.m12 = m12v; + t.m13 = m13v; + t.m21 = m21v; + t.m22 = m22v; + t.m23 = m23v; + t.mtx = m31v; + t.mty = m32v; + t.m33 = m33v; } } @@ -363,71 +360,76 @@ VMatrix VMatrix::operator*(const VMatrix &m) const return t; } -VMatrix & VMatrix::operator*=(const VMatrix &o) +VMatrix &VMatrix::operator*=(const VMatrix &o) { const MatrixType otherType = o.type(); - if (otherType == MatrixType::None) - return *this; + if (otherType == MatrixType::None) return *this; const MatrixType thisType = type(); - if (thisType == MatrixType::None) - return operator=(o); + if (thisType == MatrixType::None) return operator=(o); MatrixType t = vMax(thisType, otherType); - switch(t) { + switch (t) { case MatrixType::None: break; case MatrixType::Translate: mtx += o.mtx; mty += o.mty; break; - case MatrixType::Scale: - { - float m11v = m11*o.m11; - float m22v = m22*o.m22; + case MatrixType::Scale: { + float m11v = m11 * o.m11; + float m22v = m22 * o.m22; - float m31v = mtx*o.m11 + o.mtx; - float m32v = mty*o.m22 + o.mty; + float m31v = mtx * o.m11 + o.mtx; + float m32v = mty * o.m22 + o.mty; m11 = m11v; m22 = m22v; - mtx = m31v; mty = m32v; + mtx = m31v; + mty = m32v; break; } case MatrixType::Rotate: - case MatrixType::Shear: - { - float m11v = m11*o.m11 + m12*o.m21; - float m12v = m11*o.m12 + m12*o.m22; + case MatrixType::Shear: { + float m11v = m11 * o.m11 + m12 * o.m21; + float m12v = m11 * o.m12 + m12 * o.m22; - float m21v = m21*o.m11 + m22*o.m21; - float m22v = m21*o.m12 + m22*o.m22; + float m21v = m21 * o.m11 + m22 * o.m21; + float m22v = m21 * o.m12 + m22 * o.m22; - float m31v = mtx*o.m11 + mty*o.m21 + o.mtx; - float m32v = mtx*o.m12 + mty*o.m22 + o.mty; + float m31v = mtx * o.m11 + mty * o.m21 + o.mtx; + float m32v = mtx * o.m12 + mty * o.m22 + o.mty; - m11 = m11v; m12 = m12v; - m21 = m21v; m22 = m22v; - mtx = m31v; mty = m32v; + m11 = m11v; + m12 = m12v; + m21 = m21v; + m22 = m22v; + mtx = m31v; + mty = m32v; break; } - case MatrixType::Project: - { - float m11v = m11*o.m11 + m12*o.m21 + m13*o.mtx; - float m12v = m11*o.m12 + m12*o.m22 + m13*o.mty; - float m13v = m11*o.m13 + m12*o.m23 + m13*o.m33; - - float m21v = m21*o.m11 + m22*o.m21 + m23*o.mtx; - float m22v = m21*o.m12 + m22*o.m22 + m23*o.mty; - float m23v = m21*o.m13 + m22*o.m23 + m23*o.m33; - - float m31v = mtx*o.m11 + mty*o.m21 + m33*o.mtx; - float m32v = mtx*o.m12 + mty*o.m22 + m33*o.mty; - float m33v = mtx*o.m13 + mty*o.m23 + m33*o.m33; - - m11 = m11v; m12 = m12v; m13 = m13v; - m21 = m21v; m22 = m22v; m23 = m23v; - mtx = m31v; mty = m32v; m33 = m33v; + case MatrixType::Project: { + float m11v = m11 * o.m11 + m12 * o.m21 + m13 * o.mtx; + float m12v = m11 * o.m12 + m12 * o.m22 + m13 * o.mty; + float m13v = m11 * o.m13 + m12 * o.m23 + m13 * o.m33; + + float m21v = m21 * o.m11 + m22 * o.m21 + m23 * o.mtx; + float m22v = m21 * o.m12 + m22 * o.m22 + m23 * o.mty; + float m23v = m21 * o.m13 + m22 * o.m23 + m23 * o.m33; + + float m31v = mtx * o.m11 + mty * o.m21 + m33 * o.mtx; + float m32v = mtx * o.m12 + mty * o.m22 + m33 * o.mty; + float m33v = mtx * o.m13 + mty * o.m23 + m33 * o.m33; + + m11 = m11v; + m12 = m12v; + m13 = m13v; + m21 = m21v; + m22 = m22v; + m23 = m23v; + mtx = m31v; + mty = m32v; + m33 = m33v; } } @@ -439,18 +441,16 @@ VMatrix & VMatrix::operator*=(const VMatrix &o) VMatrix VMatrix::adjoint() const { - float h11, h12, h13, - h21, h22, h23, - h31, h32, h33; - h11 = m22*m33 - m23*mty; - h21 = m23*mtx - m21*m33; - h31 = m21*mty - m22*mtx; - h12 = m13*mty - m12*m33; - h22 = m11*m33 - m13*mtx; - h32 = m12*mtx - m11*mty; - h13 = m12*m23 - m13*m22; - h23 = m13*m21 - m11*m23; - h33 = m11*m22 - m12*m21; + float h11, h12, h13, h21, h22, h23, h31, h32, h33; + h11 = m22 * m33 - m23 * mty; + h21 = m23 * mtx - m21 * m33; + h31 = m21 * mty - m22 * mtx; + h12 = m13 * mty - m12 * m33; + h22 = m11 * m33 - m13 * mtx; + h32 = m12 * mtx - m11 * mty; + h13 = m12 * m23 - m13 * m22; + h23 = m13 * m21 - m11 * m23; + h33 = m11 * m22 - m12 * m21; VMatrix res; res.m11 = h11; @@ -471,9 +471,9 @@ VMatrix VMatrix::adjoint() const VMatrix VMatrix::inverted(bool *invertible) const { VMatrix invert; - bool inv = true; + bool inv = true; - switch(type()) { + switch (type()) { case MatrixType::None: break; case MatrixType::Translate: @@ -494,14 +494,12 @@ VMatrix VMatrix::inverted(bool *invertible) const // general case float det = determinant(); inv = !vIsZero(det); - if (inv) - invert = (adjoint() /= det); - //TODO Test above line + if (inv) invert = (adjoint() /= det); + // TODO Test above line break; } - if (invertible) - *invertible = inv; + if (invertible) *invertible = inv; if (inv) { // inverting doesn't change the type @@ -522,50 +520,47 @@ bool VMatrix::operator!=(const VMatrix &o) const return !operator==(o); } -bool VMatrix::fuzzyCompare(const VMatrix& o) const +bool VMatrix::fuzzyCompare(const VMatrix &o) const { - return vCompare(m11 , o.m11 ) - && vCompare(m12 , o.m12) - && vCompare(m21 , o.m21) - && vCompare(m22 , o.m22) - && vCompare(mtx , o.mtx) - && vCompare(mty , o.mty); + return vCompare(m11, o.m11) && vCompare(m12, o.m12) && + vCompare(m21, o.m21) && vCompare(m22, o.m22) && + vCompare(mtx, o.mtx) && vCompare(mty, o.mty); } #define V_NEAR_CLIP 0.000001 #ifdef MAP -# undef MAP +#undef MAP #endif -#define MAP(x, y, nx, ny) \ - do { \ - float FX_ = x; \ - float FY_ = y; \ - switch(t) { \ - case MatrixType::None: \ - nx = FX_; \ - ny = FY_; \ - break; \ - case MatrixType::Translate: \ - nx = FX_ + mtx; \ - ny = FY_ + mty; \ - break; \ - case MatrixType::Scale: \ - nx = m11 * FX_ + mtx; \ - ny = m22 * FY_ + mty; \ - break; \ - case MatrixType::Rotate: \ - case MatrixType::Shear: \ - case MatrixType::Project: \ - nx = m11 * FX_ + m21 * FY_ + mtx; \ - ny = m12 * FX_ + m22 * FY_ + mty; \ - if (t == MatrixType::Project) { \ - float w = ( m13 * FX_ + m23 * FY_ + m33); \ - if (w < V_NEAR_CLIP) w = V_NEAR_CLIP; \ - w = 1./w; \ - nx *= w; \ - ny *= w; \ - } \ - } \ +#define MAP(x, y, nx, ny) \ + do { \ + float FX_ = x; \ + float FY_ = y; \ + switch (t) { \ + case MatrixType::None: \ + nx = FX_; \ + ny = FY_; \ + break; \ + case MatrixType::Translate: \ + nx = FX_ + mtx; \ + ny = FY_ + mty; \ + break; \ + case MatrixType::Scale: \ + nx = m11 * FX_ + mtx; \ + ny = m22 * FY_ + mty; \ + break; \ + case MatrixType::Rotate: \ + case MatrixType::Shear: \ + case MatrixType::Project: \ + nx = m11 * FX_ + m21 * FY_ + mtx; \ + ny = m12 * FX_ + m22 * FY_ + mty; \ + if (t == MatrixType::Project) { \ + float w = (m13 * FX_ + m23 * FY_ + m33); \ + if (w < V_NEAR_CLIP) w = V_NEAR_CLIP; \ + w = 1. / w; \ + nx *= w; \ + ny *= w; \ + } \ + } \ } while (0) VRect VMatrix::map(const VRect &rect) const @@ -575,10 +570,10 @@ VRect VMatrix::map(const VRect &rect) const return rect.translated(std::round(mtx), std::round(mty)); if (t <= MatrixType::Scale) { - int x = std::round(m11*rect.x() + mtx); - int y = std::round(m22*rect.y() + mty); - int w = std::round(m11*rect.width()); - int h = std::round(m22*rect.height()); + int x = std::round(m11 * rect.x() + mtx); + int y = std::round(m22 * rect.y() + mty); + int w = std::round(m11 * rect.width()); + int h = std::round(m22 * rect.height()); if (w < 0) { w = -w; x -= w; @@ -611,7 +606,9 @@ VRect VMatrix::map(const VRect &rect) const ymin = vMin(ymin, y); xmax = vMax(xmax, x); ymax = vMax(ymax, y); - return VRect(std::round(xmin), std::round(ymin), std::round(xmax)-std::round(xmin), std::round(ymax)-std::round(ymin)); + return VRect(std::round(xmin), std::round(ymin), + std::round(xmax) - std::round(xmin), + std::round(ymax) - std::round(ymin)); } else { // Not supported assert(0); @@ -621,8 +618,7 @@ VRect VMatrix::map(const VRect &rect) const VRegion VMatrix::map(const VRegion &r) const { VMatrix::MatrixType t = type(); - if (t == MatrixType::None) - return r; + if (t == MatrixType::None) return r; if (t == MatrixType::Translate) { VRegion copy(r); @@ -645,7 +641,7 @@ VPointF VMatrix::map(const VPointF &p) const float x = 0, y = 0; VMatrix::MatrixType t = type(); - switch(t) { + switch (t) { case MatrixType::None: x = fx; y = fy; @@ -664,7 +660,7 @@ VPointF VMatrix::map(const VPointF &p) const x = m11 * fx + m21 * fy + mtx; y = m12 * fx + m22 * fy + mty; if (t == MatrixType::Project) { - float w = 1./(m13 * fx + m23 * fy + m33); + float w = 1. / (m13 * fx + m23 * fy + m33); x *= w; y *= w; } @@ -673,7 +669,7 @@ VPointF VMatrix::map(const VPointF &p) const } static std::string type_helper(VMatrix::MatrixType t) { - switch(t) { + switch (t) { case VMatrix::MatrixType::None: return "MatrixType::None"; break; @@ -695,11 +691,14 @@ static std::string type_helper(VMatrix::MatrixType t) } return ""; } -std::ostream& operator<<(std::ostream& os, const VMatrix& o) +std::ostream &operator<<(std::ostream &os, const VMatrix &o) { - os<<"[Matrix: "<<"type ="<mBuffer.prepare(buffer); mImpl->mSpanData.init(&mImpl->mBuffer); - //TODO find a better api to clear the surface + // TODO find a better api to clear the surface mImpl->mBuffer.clear(); return true; } -void VPainter::end() -{ - -} +void VPainter::end() {} void VPainter::setBrush(const VBrush &brush) { diff --git a/src/vector/vpainter.h b/src/vector/vpainter.h index f488446..67942a2 100644 --- a/src/vector/vpainter.h +++ b/src/vector/vpainter.h @@ -1,9 +1,9 @@ #ifndef VPAINTER_H #define VPAINTER_H -#include"vpoint.h" -#include"vrle.h" -#include"vbrush.h" +#include "vbrush.h" +#include "vpoint.h" +#include "vrle.h" V_BEGIN_NAMESPACE @@ -11,22 +11,20 @@ class VBitmap; class VPainterImpl; class VPainter { public: - enum CompositionMode{ - CompModeSrc, - CompModeSrcOver - }; + enum CompositionMode { CompModeSrc, CompModeSrcOver }; ~VPainter(); VPainter(); VPainter(VBitmap *buffer); - bool begin(VBitmap *buffer); - void end(); - void setBrush(const VBrush &brush); - void drawRle(const VPoint &pos, const VRle &rle); + bool begin(VBitmap *buffer); + void end(); + void setBrush(const VBrush &brush); + void drawRle(const VPoint &pos, const VRle &rle); VRect clipBoundingRect() const; + private: - VPainterImpl *mImpl; + VPainterImpl *mImpl; }; V_END_NAMESPACE -#endif //VPAINTER_H +#endif // VPAINTER_H diff --git a/src/vector/vpath.cpp b/src/vector/vpath.cpp index 1724f8f..043bdcf 100644 --- a/src/vector/vpath.cpp +++ b/src/vector/vpath.cpp @@ -1,70 +1,70 @@ -#include"vpath.h" -#include -#include -#include"vdebug.h" -#include"vbezier.h" +#include "vpath.h" +#include +#include +#include "vbezier.h" +#include "vdebug.h" #include "vrect.h" V_BEGIN_NAMESPACE -VPath::VPathData::VPathData():m_points(), - m_elements(), - m_segments(0), - mStartPoint(), - mNewSegment(true){} +VPath::VPathData::VPathData() + : m_points(), m_elements(), m_segments(0), mStartPoint(), mNewSegment(true) +{ +} -VPath::VPathData::VPathData(const VPathData &o):m_points(o.m_points), - m_elements(o.m_elements), - m_segments(o.m_segments), - mStartPoint(o.mStartPoint), - mNewSegment(o.mNewSegment){} +VPath::VPathData::VPathData(const VPathData &o) + : m_points(o.m_points), + m_elements(o.m_elements), + m_segments(o.m_segments), + mStartPoint(o.mStartPoint), + mNewSegment(o.mNewSegment) +{ +} void VPath::VPathData::transform(const VMatrix &m) { - for(auto &i : m_points) { + for (auto &i : m_points) { i = m.map(i); } } float VPath::VPathData::length() const { - float len = 0.0; - int i = 0; - for (auto e : m_elements) { + float len = 0.0; + int i = 0; + for (auto e : m_elements) { switch (e) { - case VPath::Element::MoveTo: - i++; - break; - case VPath::Element::LineTo: - { - VPointF p0 = m_points[i - 1]; - VPointF p = m_points[i++]; - VBezier b = VBezier::fromPoints(p0, p0, p, p); - len += b.length(); - break; - } - case VPath::Element::CubicTo: - { - VPointF p0 = m_points[i - 1]; - VPointF p = m_points[i++]; - VPointF p1 = m_points[i++]; - VPointF p2 = m_points[i++]; - VBezier b = VBezier::fromPoints(p0, p, p1, p2); - len += b.length(); - break; - } - case VPath::Element::Close: - break; + case VPath::Element::MoveTo: + i++; + break; + case VPath::Element::LineTo: { + VPointF p0 = m_points[i - 1]; + VPointF p = m_points[i++]; + VBezier b = VBezier::fromPoints(p0, p0, p, p); + len += b.length(); + break; + } + case VPath::Element::CubicTo: { + VPointF p0 = m_points[i - 1]; + VPointF p = m_points[i++]; + VPointF p1 = m_points[i++]; + VPointF p2 = m_points[i++]; + VBezier b = VBezier::fromPoints(p0, p, p1, p2); + len += b.length(); + break; } - } + case VPath::Element::Close: + break; + } + } - return len; + return len; } void VPath::VPathData::checkNewSegment() { if (mNewSegment) { - moveTo(VPointF(0,0)); + moveTo(VPointF(0, 0)); mNewSegment = false; } } @@ -83,7 +83,8 @@ void VPath::VPathData::lineTo(const VPointF &p) m_elements.push_back(VPath::Element::LineTo); m_points.push_back(p); } -void VPath::VPathData::cubicTo(const VPointF &c1, const VPointF &c2, const VPointF &e) +void VPath::VPathData::cubicTo(const VPointF &c1, const VPointF &c2, + const VPointF &e) { checkNewSegment(); m_elements.push_back(VPath::Element::CubicTo); @@ -98,7 +99,7 @@ void VPath::VPathData::close() const VPointF &lastPt = m_points.back(); if (!fuzzyCompare(mStartPoint, lastPt)) { - lineTo(mStartPoint); + lineTo(mStartPoint); } m_elements.push_back(VPath::Element::Close); mNewSegment = true; @@ -127,25 +128,28 @@ void VPath::VPathData::reserve(int pts, int elms) static VPointF curvesForArc(const VRectF &, float, float, VPointF *, int *); static constexpr float PATH_KAPPA = 0.5522847498; -void VPath::VPathData::arcTo(const VRectF &rect, float startAngle, float sweepLength, bool forceMoveTo) +void VPath::VPathData::arcTo(const VRectF &rect, float startAngle, + float sweepLength, bool forceMoveTo) { - int point_count = 0; + int point_count = 0; VPointF pts[15]; - VPointF curve_start = curvesForArc(rect, startAngle, sweepLength, pts, &point_count); + VPointF curve_start = + curvesForArc(rect, startAngle, sweepLength, pts, &point_count); if (isEmpty() || forceMoveTo) { moveTo(curve_start); } else { lineTo(curve_start); } - for (int i=0; i 3 o'clock - cubicTo(VPointF(x + w2 + w2k, y), VPointF(x + w, y + h2 - h2k), VPointF(x + w, y + h2)); - // 3 -> 6 o'clock - cubicTo(VPointF(x + w, y + h2 + h2k), VPointF(x + w2 + w2k, y + h), VPointF(x + w2, y + h)); - // 6 -> 9 o'clock - cubicTo(VPointF(x + w2 - w2k, y + h), VPointF(x, y + h2 + h2k), VPointF(x , y + h2)); - // 9 -> 12 o'clock - cubicTo(VPointF(x, y + h2 - h2k), VPointF(x + w2 - w2k, y), VPointF(x + w2, y)); + // moveto 12 o'clock. + moveTo(VPointF(x + w2, y)); + // 12 -> 3 o'clock + cubicTo(VPointF(x + w2 + w2k, y), VPointF(x + w, y + h2 - h2k), + VPointF(x + w, y + h2)); + // 3 -> 6 o'clock + cubicTo(VPointF(x + w, y + h2 + h2k), VPointF(x + w2 + w2k, y + h), + VPointF(x + w2, y + h)); + // 6 -> 9 o'clock + cubicTo(VPointF(x + w2 - w2k, y + h), VPointF(x, y + h2 + h2k), + VPointF(x, y + h2)); + // 9 -> 12 o'clock + cubicTo(VPointF(x, y + h2 - h2k), VPointF(x + w2 - w2k, y), + VPointF(x + w2, y)); } else { - // moveto 12 o'clock. - moveTo(VPointF(x+w2, y)); - // 12 -> 9 o'clock - cubicTo(VPointF(x + w2 - w2k, y), VPointF(x, y + h2 - h2k), VPointF(x , y + h2)); - // 9 -> 6 o'clock - cubicTo(VPointF(x, y + h2 + h2k), VPointF(x + w2 - w2k, y + h), VPointF(x + w2, y + h)); - // 6 -> 3 o'clock - cubicTo(VPointF(x + w2 + w2k, y + h), VPointF(x + w, y + h2 + h2k), VPointF(x + w, y + h2)); - // 3 -> 12 o'clock - cubicTo(VPointF(x + w, y + h2 - h2k), VPointF(x + w2 + w2k, y), VPointF(x+w2, y)); + // moveto 12 o'clock. + moveTo(VPointF(x + w2, y)); + // 12 -> 9 o'clock + cubicTo(VPointF(x + w2 - w2k, y), VPointF(x, y + h2 - h2k), + VPointF(x, y + h2)); + // 9 -> 6 o'clock + cubicTo(VPointF(x, y + h2 + h2k), VPointF(x + w2 - w2k, y + h), + VPointF(x + w2, y + h)); + // 6 -> 3 o'clock + cubicTo(VPointF(x + w2 + w2k, y + h), VPointF(x + w, y + h2 + h2k), + VPointF(x + w, y + h2)); + // 3 -> 12 o'clock + cubicTo(VPointF(x + w, y + h2 - h2k), VPointF(x + w2 + w2k, y), + VPointF(x + w2, y)); } } @@ -199,21 +210,22 @@ void VPath::VPathData::addRect(const VRectF &rect, VPath::Direction dir) float h = rect.height(); if (dir == VPath::Direction::CW) { - moveTo(VPointF(x + w, y)); - lineTo(VPointF(x + w, y + h)); - lineTo(VPointF(x , y + h)); - lineTo(VPointF(x , y)); - close(); + moveTo(VPointF(x + w, y)); + lineTo(VPointF(x + w, y + h)); + lineTo(VPointF(x, y + h)); + lineTo(VPointF(x, y)); + close(); } else { - moveTo(VPointF(x + w, y)); - lineTo(VPointF(x , y)); - lineTo(VPointF(x , y + h)); - lineTo(VPointF(x + w, y + h)); - close(); + moveTo(VPointF(x + w, y)); + lineTo(VPointF(x, y)); + lineTo(VPointF(x, y + h)); + lineTo(VPointF(x + w, y + h)); + close(); } } -void VPath::VPathData::addRoundRect(const VRectF &rect, float rx, float ry, VPath::Direction dir) +void VPath::VPathData::addRoundRect(const VRectF &rect, float rx, float ry, + VPath::Direction dir) { if (vCompare(rx, 0.f) || vCompare(ry, 0.f)) { addRect(rect, dir); @@ -225,49 +237,46 @@ void VPath::VPathData::addRoundRect(const VRectF &rect, float rx, float ry, VPat float w = rect.width(); float h = rect.height(); // clamp the rx and ry radius value. - rx = 2*rx; - ry = 2*ry; + rx = 2 * rx; + ry = 2 * ry; if (rx > w) rx = w; if (ry > h) ry = h; - if (dir == VPath::Direction::CW) { - moveTo(VPointF(x + w, y + ry/2.f)); - arcTo(VRectF(x + w - rx, y + h - ry, rx, ry), 0 , -90, false); - arcTo(VRectF(x, y + h - ry, rx, ry), -90 , -90, false); - arcTo(VRectF(x, y, rx, ry), -180 , -90, false); - arcTo(VRectF(x + w - rx, y, rx, ry), -270 , -90, false); - close(); - } else { - moveTo(VPointF(x + w, y + ry/2.f)); - arcTo(VRectF(x + w - rx, y , rx, ry), 0 , 90, false); - arcTo(VRectF(x, y, rx, ry), 90 , 90, false); - arcTo(VRectF(x, y + h - ry, rx, ry), 180 , 90, false); - arcTo(VRectF(x + w - rx, y + h - ry, rx, ry), 270 , 90, false); - close(); - } + if (dir == VPath::Direction::CW) { + moveTo(VPointF(x + w, y + ry / 2.f)); + arcTo(VRectF(x + w - rx, y + h - ry, rx, ry), 0, -90, false); + arcTo(VRectF(x, y + h - ry, rx, ry), -90, -90, false); + arcTo(VRectF(x, y, rx, ry), -180, -90, false); + arcTo(VRectF(x + w - rx, y, rx, ry), -270, -90, false); + close(); + } else { + moveTo(VPointF(x + w, y + ry / 2.f)); + arcTo(VRectF(x + w - rx, y, rx, ry), 0, 90, false); + arcTo(VRectF(x, y, rx, ry), 90, 90, false); + arcTo(VRectF(x, y + h - ry, rx, ry), 180, 90, false); + arcTo(VRectF(x + w - rx, y + h - ry, rx, ry), 270, 90, false); + close(); + } } static float tForArcAngle(float angle); -void findEllipseCoords(const VRectF &r, float angle, float length, - VPointF* startPoint, VPointF *endPoint) +void findEllipseCoords(const VRectF &r, float angle, float length, + VPointF *startPoint, VPointF *endPoint) { if (r.isNull()) { - if (startPoint) - *startPoint = VPointF(); - if (endPoint) - *endPoint = VPointF(); + if (startPoint) *startPoint = VPointF(); + if (endPoint) *endPoint = VPointF(); return; } float w2 = r.width() / 2; float h2 = r.height() / 2; - float angles[2] = { angle, angle + length }; - VPointF *points[2] = { startPoint, endPoint }; + float angles[2] = {angle, angle + length}; + VPointF *points[2] = {startPoint, endPoint}; for (int i = 0; i < 2; ++i) { - if (!points[i]) - continue; + if (!points[i]) continue; float theta = angles[i] - 360 * floor(angles[i] / 360); float t = theta / 90; @@ -278,68 +287,75 @@ void findEllipseCoords(const VRectF &r, float angle, float length, t = tForArcAngle(90 * t); // swap x and y? - if (quadrant & 1) - t = 1 - t; + if (quadrant & 1) t = 1 - t; float a, b, c, d; VBezier::coefficients(t, a, b, c, d); - VPointF p(a + b + c*PATH_KAPPA, d + c + b*PATH_KAPPA); + VPointF p(a + b + c * PATH_KAPPA, d + c + b * PATH_KAPPA); // left quadrants - if (quadrant == 1 || quadrant == 2) - p.rx() = -p.x(); + if (quadrant == 1 || quadrant == 2) p.rx() = -p.x(); // top quadrants - if (quadrant == 0 || quadrant == 1) - p.ry() = -p.y(); + if (quadrant == 0 || quadrant == 1) p.ry() = -p.y(); *points[i] = r.center() + VPointF(w2 * p.x(), h2 * p.y()); } } -static float -tForArcAngle(float angle) +static float tForArcAngle(float angle) { - float radians, cos_angle, sin_angle, tc, ts, t; - - if (vCompare(angle,0.f)) return 0; - if (vCompare(angle, 90.0f)) return 1; - - radians = (angle/180) * M_PI; - - cos_angle = cos(radians); - sin_angle = sin(radians); - - // initial guess - tc = angle / 90; - - // do some iterations of newton's method to approximate cos_angle - // finds the zero of the function b.pointAt(tc).x() - cos_angle - tc -= ((((2-3*PATH_KAPPA) * tc + 3*(PATH_KAPPA-1)) * tc) * tc + 1 - cos_angle) // value - / (((6-9*PATH_KAPPA) * tc + 6*(PATH_KAPPA-1)) * tc); // derivative - tc -= ((((2-3*PATH_KAPPA) * tc + 3*(PATH_KAPPA-1)) * tc) * tc + 1 - cos_angle) // value - / (((6-9*PATH_KAPPA) * tc + 6*(PATH_KAPPA-1)) * tc); // derivative - - // initial guess - ts = tc; - // do some iterations of newton's method to approximate sin_angle - // finds the zero of the function b.pointAt(tc).y() - sin_angle - ts -= ((((3*PATH_KAPPA-2) * ts - 6*PATH_KAPPA + 3) * ts + 3*PATH_KAPPA) * ts - sin_angle) - / (((9*PATH_KAPPA-6) * ts + 12*PATH_KAPPA - 6) * ts + 3*PATH_KAPPA); - ts -= ((((3*PATH_KAPPA-2) * ts - 6*PATH_KAPPA + 3) * ts + 3*PATH_KAPPA) * ts - sin_angle) - / (((9*PATH_KAPPA-6) * ts + 12*PATH_KAPPA - 6) * ts + 3*PATH_KAPPA); - - // use the average of the t that best approximates cos_angle - // and the t that best approximates sin_angle - t = 0.5 * (tc + ts); - return t; + float radians, cos_angle, sin_angle, tc, ts, t; + + if (vCompare(angle, 0.f)) return 0; + if (vCompare(angle, 90.0f)) return 1; + + radians = (angle / 180) * M_PI; + + cos_angle = cos(radians); + sin_angle = sin(radians); + + // initial guess + tc = angle / 90; + + // do some iterations of newton's method to approximate cos_angle + // finds the zero of the function b.pointAt(tc).x() - cos_angle + tc -= ((((2 - 3 * PATH_KAPPA) * tc + 3 * (PATH_KAPPA - 1)) * tc) * tc + 1 - + cos_angle) // value + / (((6 - 9 * PATH_KAPPA) * tc + 6 * (PATH_KAPPA - 1)) * + tc); // derivative + tc -= ((((2 - 3 * PATH_KAPPA) * tc + 3 * (PATH_KAPPA - 1)) * tc) * tc + 1 - + cos_angle) // value + / (((6 - 9 * PATH_KAPPA) * tc + 6 * (PATH_KAPPA - 1)) * + tc); // derivative + + // initial guess + ts = tc; + // do some iterations of newton's method to approximate sin_angle + // finds the zero of the function b.pointAt(tc).y() - sin_angle + ts -= ((((3 * PATH_KAPPA - 2) * ts - 6 * PATH_KAPPA + 3) * ts + + 3 * PATH_KAPPA) * + ts - + sin_angle) / + (((9 * PATH_KAPPA - 6) * ts + 12 * PATH_KAPPA - 6) * ts + + 3 * PATH_KAPPA); + ts -= ((((3 * PATH_KAPPA - 2) * ts - 6 * PATH_KAPPA + 3) * ts + + 3 * PATH_KAPPA) * + ts - + sin_angle) / + (((9 * PATH_KAPPA - 6) * ts + 12 * PATH_KAPPA - 6) * ts + + 3 * PATH_KAPPA); + + // use the average of the t that best approximates cos_angle + // and the t that best approximates sin_angle + t = 0.5 * (tc + ts); + return t; } - // The return value is the starting point of the arc -static VPointF -curvesForArc(const VRectF &rect, float startAngle, float sweepLength, - VPointF *curves, int *point_count) +static VPointF curvesForArc(const VRectF &rect, float startAngle, + float sweepLength, VPointF *curves, + int *point_count) { if (rect.isNull()) { return VPointF(); @@ -356,44 +372,37 @@ curvesForArc(const VRectF &rect, float startAngle, float sweepLength, float h2 = rect.height() / 2; float h2k = h2 * PATH_KAPPA; - VPointF points[16] = - { + VPointF points[16] = { // start point VPointF(x + w, y + h2), // 0 -> 270 degrees - VPointF(x + w, y + h2 + h2k), - VPointF(x + w2 + w2k, y + h), + VPointF(x + w, y + h2 + h2k), VPointF(x + w2 + w2k, y + h), VPointF(x + w2, y + h), // 270 -> 180 degrees - VPointF(x + w2 - w2k, y + h), - VPointF(x, y + h2 + h2k), + VPointF(x + w2 - w2k, y + h), VPointF(x, y + h2 + h2k), VPointF(x, y + h2), // 180 -> 90 degrees - VPointF(x, y + h2 - h2k), - VPointF(x + w2 - w2k, y), - VPointF(x + w2, y), + VPointF(x, y + h2 - h2k), VPointF(x + w2 - w2k, y), VPointF(x + w2, y), // 90 -> 0 degrees - VPointF(x + w2 + w2k, y), - VPointF(x + w, y + h2 - h2k), - VPointF(x + w, y + h2) - }; + VPointF(x + w2 + w2k, y), VPointF(x + w, y + h2 - h2k), + VPointF(x + w, y + h2)}; - if (sweepLength > 360) sweepLength = 360; - else if (sweepLength < -360) sweepLength = -360; + if (sweepLength > 360) + sweepLength = 360; + else if (sweepLength < -360) + sweepLength = -360; // Special case fast paths if (startAngle == 0.0) { if (sweepLength == 360.0) { - for (int i = 11; i >= 0; --i) - curves[(*point_count)++] = points[i]; + for (int i = 11; i >= 0; --i) curves[(*point_count)++] = points[i]; return points[12]; } else if (sweepLength == -360.0) { - for (int i = 1; i <= 12; ++i) - curves[(*point_count)++] = points[i]; + for (int i = 1; i <= 12; ++i) curves[(*point_count)++] = points[i]; return points[0]; } } @@ -446,9 +455,11 @@ curvesForArc(const VRectF &rect, float startAngle, float sweepLength, VBezier b; if (delta > 0) - b = VBezier::fromPoints(points[j + 3], points[j + 2], points[j + 1], points[j]); + b = VBezier::fromPoints(points[j + 3], points[j + 2], points[j + 1], + points[j]); else - b = VBezier::fromPoints(points[j], points[j + 1], points[j + 2], points[j + 3]); + b = VBezier::fromPoints(points[j], points[j + 1], points[j + 2], + points[j + 3]); // empty arc? if (startSegment == endSegment && vCompare(startT, endT)) @@ -474,151 +485,160 @@ curvesForArc(const VRectF &rect, float startAngle, float sweepLength, return startPoint; } -void VPath::VPathData::addPolystar(float points, float innerRadius, float outerRadius, - float innerRoundness, float outerRoundness, - float startAngle, float cx, float cy, VPath::Direction dir) +void VPath::VPathData::addPolystar(float points, float innerRadius, + float outerRadius, float innerRoundness, + float outerRoundness, float startAngle, + float cx, float cy, VPath::Direction dir) { - const static float POLYSTAR_MAGIC_NUMBER = 0.47829 / 0.28; - float currentAngle = (startAngle - 90.0) * M_PI / 180.0; - float x; - float y; - float previousX; - float previousY; - float partialPointRadius = 0; - float anglePerPoint = (float) (2.0 * M_PI / points); - float halfAnglePerPoint = anglePerPoint / 2.0; - float partialPointAmount = points - (int) points; - bool longSegment = false; - int numPoints = (int) ceil(points) * 2.0; - float angleDir = ((dir == VPath::Direction::CW) ? 1.0 : -1.0); - - innerRoundness /= 100.0; - outerRoundness /= 100.0; - - if (partialPointAmount != 0) { - currentAngle += halfAnglePerPoint * (1.0 - partialPointAmount) * angleDir; - } - - if (partialPointAmount != 0) { - partialPointRadius = innerRadius + partialPointAmount * (outerRadius - innerRadius); - x = (float) (partialPointRadius * cos(currentAngle)); - y = (float) (partialPointRadius * sin(currentAngle)); + const static float POLYSTAR_MAGIC_NUMBER = 0.47829 / 0.28; + float currentAngle = (startAngle - 90.0) * M_PI / 180.0; + float x; + float y; + float previousX; + float previousY; + float partialPointRadius = 0; + float anglePerPoint = (float)(2.0 * M_PI / points); + float halfAnglePerPoint = anglePerPoint / 2.0; + float partialPointAmount = points - (int)points; + bool longSegment = false; + int numPoints = (int)ceil(points) * 2.0; + float angleDir = ((dir == VPath::Direction::CW) ? 1.0 : -1.0); + + innerRoundness /= 100.0; + outerRoundness /= 100.0; + + if (partialPointAmount != 0) { + currentAngle += + halfAnglePerPoint * (1.0 - partialPointAmount) * angleDir; + } + + if (partialPointAmount != 0) { + partialPointRadius = + innerRadius + partialPointAmount * (outerRadius - innerRadius); + x = (float)(partialPointRadius * cos(currentAngle)); + y = (float)(partialPointRadius * sin(currentAngle)); currentAngle += anglePerPoint * partialPointAmount / 2.0 * angleDir; - } else { - x = (float) (outerRadius * cos(currentAngle)); - y = (float) (outerRadius * sin(currentAngle)); + } else { + x = (float)(outerRadius * cos(currentAngle)); + y = (float)(outerRadius * sin(currentAngle)); currentAngle += halfAnglePerPoint * angleDir; - } + } - moveTo(VPointF(x + cx, y + cy)); + moveTo(VPointF(x + cx, y + cy)); - for (int i = 0; i < numPoints; i++) { + for (int i = 0; i < numPoints; i++) { float radius = longSegment ? outerRadius : innerRadius; float dTheta = halfAnglePerPoint; if (partialPointRadius != 0 && i == numPoints - 2) { - dTheta = anglePerPoint * partialPointAmount / 2.0; + dTheta = anglePerPoint * partialPointAmount / 2.0; } if (partialPointRadius != 0 && i == numPoints - 1) { - radius = partialPointRadius; + radius = partialPointRadius; } previousX = x; previousY = y; - x = (float) (radius * cos(currentAngle)); - y = (float) (radius * sin(currentAngle)); + x = (float)(radius * cos(currentAngle)); + y = (float)(radius * sin(currentAngle)); if (innerRoundness == 0 && outerRoundness == 0) { - lineTo(VPointF(x + cx, y + cy)); + lineTo(VPointF(x + cx, y + cy)); } else { - float cp1Theta = (float) (atan2(previousY, previousX) - M_PI / 2.0 * angleDir); - float cp1Dx = (float) cos(cp1Theta); - float cp1Dy = (float) sin(cp1Theta); - float cp2Theta = (float) (atan2(y, x) - M_PI / 2.0 * angleDir); - float cp2Dx = (float) cos(cp2Theta); - float cp2Dy = (float) sin(cp2Theta); - - float cp1Roundness = longSegment ? innerRoundness : outerRoundness; - float cp2Roundness = longSegment ? outerRoundness : innerRoundness; - float cp1Radius = longSegment ? innerRadius : outerRadius; - float cp2Radius = longSegment ? outerRadius : innerRadius; - - float cp1x = cp1Radius * cp1Roundness * POLYSTAR_MAGIC_NUMBER * cp1Dx / points; - float cp1y = cp1Radius * cp1Roundness * POLYSTAR_MAGIC_NUMBER * cp1Dy / points; - float cp2x = cp2Radius * cp2Roundness * POLYSTAR_MAGIC_NUMBER * cp2Dx / points; - float cp2y = cp2Radius * cp2Roundness * POLYSTAR_MAGIC_NUMBER * cp2Dy / points; - - if ((partialPointAmount != 0) && - ((i == 0) || (i == numPoints - 1))) { - cp1x *= partialPointAmount; - cp1y *= partialPointAmount; - cp2x *= partialPointAmount; - cp2y *= partialPointAmount; - } - - cubicTo(VPointF(previousX - cp1x + cx, previousY - cp1y + cy), - VPointF(x + cp2x + cx, y + cp2y + cy), - VPointF(x + cx, y + cy)); + float cp1Theta = + (float)(atan2(previousY, previousX) - M_PI / 2.0 * angleDir); + float cp1Dx = (float)cos(cp1Theta); + float cp1Dy = (float)sin(cp1Theta); + float cp2Theta = (float)(atan2(y, x) - M_PI / 2.0 * angleDir); + float cp2Dx = (float)cos(cp2Theta); + float cp2Dy = (float)sin(cp2Theta); + + float cp1Roundness = longSegment ? innerRoundness : outerRoundness; + float cp2Roundness = longSegment ? outerRoundness : innerRoundness; + float cp1Radius = longSegment ? innerRadius : outerRadius; + float cp2Radius = longSegment ? outerRadius : innerRadius; + + float cp1x = cp1Radius * cp1Roundness * POLYSTAR_MAGIC_NUMBER * + cp1Dx / points; + float cp1y = cp1Radius * cp1Roundness * POLYSTAR_MAGIC_NUMBER * + cp1Dy / points; + float cp2x = cp2Radius * cp2Roundness * POLYSTAR_MAGIC_NUMBER * + cp2Dx / points; + float cp2y = cp2Radius * cp2Roundness * POLYSTAR_MAGIC_NUMBER * + cp2Dy / points; + + if ((partialPointAmount != 0) && + ((i == 0) || (i == numPoints - 1))) { + cp1x *= partialPointAmount; + cp1y *= partialPointAmount; + cp2x *= partialPointAmount; + cp2y *= partialPointAmount; + } + + cubicTo(VPointF(previousX - cp1x + cx, previousY - cp1y + cy), + VPointF(x + cp2x + cx, y + cp2y + cy), + VPointF(x + cx, y + cy)); } currentAngle += dTheta * angleDir; longSegment = !longSegment; - } + } - close(); + close(); } void VPath::VPathData::addPolygon(float points, float radius, float roundness, - float startAngle, float cx, float cy, VPath::Direction dir) + float startAngle, float cx, float cy, + VPath::Direction dir) { - // TODO: Need to support floating point number for number of points - const static float POLYGON_MAGIC_NUMBER = 0.25; - float currentAngle = (startAngle - 90.0) * M_PI / 180.0; - float x; - float y; - float previousX; - float previousY; - float anglePerPoint = (float) (2.0 * M_PI / floor(points)); - int numPoints = (int) floor(points); - float angleDir = ((dir == VPath::Direction::CW) ? 1.0 : -1.0); - - roundness /= 100.0; - - currentAngle = (currentAngle - 90.0) * M_PI / 180.0; - x = (float) (radius * cos(currentAngle)); - y = (float) (radius * sin(currentAngle)); - currentAngle += anglePerPoint * angleDir; - - moveTo(VPointF(x + cx, y + cy)); - - for (int i = 0; i < numPoints; i++) { + // TODO: Need to support floating point number for number of points + const static float POLYGON_MAGIC_NUMBER = 0.25; + float currentAngle = (startAngle - 90.0) * M_PI / 180.0; + float x; + float y; + float previousX; + float previousY; + float anglePerPoint = (float)(2.0 * M_PI / floor(points)); + int numPoints = (int)floor(points); + float angleDir = ((dir == VPath::Direction::CW) ? 1.0 : -1.0); + + roundness /= 100.0; + + currentAngle = (currentAngle - 90.0) * M_PI / 180.0; + x = (float)(radius * cos(currentAngle)); + y = (float)(radius * sin(currentAngle)); + currentAngle += anglePerPoint * angleDir; + + moveTo(VPointF(x + cx, y + cy)); + + for (int i = 0; i < numPoints; i++) { previousX = x; previousY = y; - x = (float) (radius * cos(currentAngle)); - y = (float) (radius * sin(currentAngle)); + x = (float)(radius * cos(currentAngle)); + y = (float)(radius * sin(currentAngle)); if (roundness != 0) { - float cp1Theta = (float) (atan2(previousY, previousX) - M_PI / 2.0 * angleDir); - float cp1Dx = (float) cos(cp1Theta); - float cp1Dy = (float) sin(cp1Theta); - float cp2Theta = (float) (atan2(y, x) - M_PI / 2.0 * angleDir); - float cp2Dx = (float) cos(cp2Theta); - float cp2Dy = (float) sin(cp2Theta); - - float cp1x = radius * roundness * POLYGON_MAGIC_NUMBER * cp1Dx; - float cp1y = radius * roundness * POLYGON_MAGIC_NUMBER * cp1Dy; - float cp2x = radius * roundness * POLYGON_MAGIC_NUMBER * cp2Dx; - float cp2y = radius * roundness * POLYGON_MAGIC_NUMBER * cp2Dy; - - cubicTo(VPointF(previousX - cp1x + cx, previousY - cp1y + cy), - VPointF(x + cp2x + cx, y + cp2y + cy), - VPointF(x, y)); + float cp1Theta = + (float)(atan2(previousY, previousX) - M_PI / 2.0 * angleDir); + float cp1Dx = (float)cos(cp1Theta); + float cp1Dy = (float)sin(cp1Theta); + float cp2Theta = (float)(atan2(y, x) - M_PI / 2.0 * angleDir); + float cp2Dx = (float)cos(cp2Theta); + float cp2Dy = (float)sin(cp2Theta); + + float cp1x = radius * roundness * POLYGON_MAGIC_NUMBER * cp1Dx; + float cp1y = radius * roundness * POLYGON_MAGIC_NUMBER * cp1Dy; + float cp2x = radius * roundness * POLYGON_MAGIC_NUMBER * cp2Dx; + float cp2y = radius * roundness * POLYGON_MAGIC_NUMBER * cp2Dy; + + cubicTo(VPointF(previousX - cp1x + cx, previousY - cp1y + cy), + VPointF(x + cp2x + cx, y + cp2y + cy), VPointF(x, y)); } else { - lineTo(VPointF(x + cx, y + cy)); + lineTo(VPointF(x + cx, y + cy)); } currentAngle += anglePerPoint * angleDir; - } + } - close(); + close(); } V_END_NAMESPACE diff --git a/src/vector/vpath.h b/src/vector/vpath.h index 2782861..2d1858d 100644 --- a/src/vector/vpath.h +++ b/src/vector/vpath.h @@ -1,91 +1,94 @@ #ifndef VPATH_H #define VPATH_H +#include +#include "vcowptr.h" +#include "vmatrix.h" #include "vpoint.h" #include "vrect.h" -#include "vmatrix.h" -#include -#include V_BEGIN_NAMESPACE struct VPathData; -class VPath -{ +class VPath { public: - enum class Direction { - CCW, - CW - }; - - enum class Element : uchar { - MoveTo, - LineTo, - CubicTo, - Close - }; - bool isEmpty()const; - void moveTo(const VPointF &p); - void moveTo(float x, float y); - void lineTo(const VPointF &p); - void lineTo(float x, float y); - void cubicTo(const VPointF &c1, const VPointF &c2, const VPointF &e); - void cubicTo(float c1x, float c1y, float c2x, float c2y, float ex, float ey); - void arcTo(const VRectF &rect, float startAngle, float sweepLength, bool forceMoveTo); - void close(); - void reset(); - void reserve(int pts, int elms); - int segments() const; - void addCircle(float cx, float cy, float radius, VPath::Direction dir = Direction::CW); - void addOval(const VRectF &rect, VPath::Direction dir = Direction::CW); - void addRoundRect(const VRectF &rect, float rx, float ry, VPath::Direction dir = Direction::CW); - void addRect(const VRectF &rect, VPath::Direction dir = Direction::CW); - void addPolystar(float points, float innerRadius, float outerRadius, - float innerRoundness, float outerRoundness, - float startAngle, float cx, float cy, VPath::Direction dir = Direction::CW); - void addPolygon(float points, float radius, float roundness, - float startAngle, float cx, float cy, VPath::Direction dir = Direction::CW); - void transform(const VMatrix &m); + enum class Direction { CCW, CW }; + + enum class Element : uchar { MoveTo, LineTo, CubicTo, Close }; + bool isEmpty() const; + void moveTo(const VPointF &p); + void moveTo(float x, float y); + void lineTo(const VPointF &p); + void lineTo(float x, float y); + void cubicTo(const VPointF &c1, const VPointF &c2, const VPointF &e); + void cubicTo(float c1x, float c1y, float c2x, float c2y, float ex, + float ey); + void arcTo(const VRectF &rect, float startAngle, float sweepLength, + bool forceMoveTo); + void close(); + void reset(); + void reserve(int pts, int elms); + int segments() const; + void addCircle(float cx, float cy, float radius, + VPath::Direction dir = Direction::CW); + void addOval(const VRectF &rect, VPath::Direction dir = Direction::CW); + void addRoundRect(const VRectF &rect, float rx, float ry, + VPath::Direction dir = Direction::CW); + void addRect(const VRectF &rect, VPath::Direction dir = Direction::CW); + void addPolystar(float points, float innerRadius, float outerRadius, + float innerRoundness, float outerRoundness, + float startAngle, float cx, float cy, + VPath::Direction dir = Direction::CW); + void addPolygon(float points, float radius, float roundness, + float startAngle, float cx, float cy, + VPath::Direction dir = Direction::CW); + void transform(const VMatrix &m); float length() const; const std::vector &elements() const; - const std::vector &points() const; + const std::vector & points() const; + private: struct VPathData { VPathData(); VPathData(const VPathData &o); - bool isEmpty() const { return m_elements.empty();} - void moveTo(const VPointF &pt); - void lineTo(const VPointF &pt); - void cubicTo(const VPointF &c1, const VPointF &c2, const VPointF &e); - void close(); - void reset(); - void reserve(int, int); - void checkNewSegment(); - int segments() const; - void transform(const VMatrix &m); + bool isEmpty() const { return m_elements.empty(); } + void moveTo(const VPointF &pt); + void lineTo(const VPointF &pt); + void cubicTo(const VPointF &c1, const VPointF &c2, const VPointF &e); + void close(); + void reset(); + void reserve(int, int); + void checkNewSegment(); + int segments() const; + void transform(const VMatrix &m); float length() const; - void addRoundRect(const VRectF &, float, float, VPath::Direction); - void addRect(const VRectF &, VPath::Direction); - void arcTo(const VRectF&, float, float, bool); - void addCircle(float, float, float, VPath::Direction); - void addOval(const VRectF &, VPath::Direction); - void addPolystar(float points, float innerRadius, float outerRadius, - float innerRoundness, float outerRoundness, - float startAngle, float cx, float cy, VPath::Direction dir = Direction::CW); - void addPolygon(float points, float radius, float roundness, - float startAngle, float cx, float cy, VPath::Direction dir = Direction::CW); - const std::vector &elements() const { return m_elements;} - const std::vector &points() const {return m_points;} - std::vector m_points; - std::vector m_elements; - int m_segments; - VPointF mStartPoint; - bool mNewSegment; + void addRoundRect(const VRectF &, float, float, VPath::Direction); + void addRect(const VRectF &, VPath::Direction); + void arcTo(const VRectF &, float, float, bool); + void addCircle(float, float, float, VPath::Direction); + void addOval(const VRectF &, VPath::Direction); + void addPolystar(float points, float innerRadius, float outerRadius, + float innerRoundness, float outerRoundness, + float startAngle, float cx, float cy, + VPath::Direction dir = Direction::CW); + void addPolygon(float points, float radius, float roundness, + float startAngle, float cx, float cy, + VPath::Direction dir = Direction::CW); + const std::vector &elements() const + { + return m_elements; + } + const std::vector &points() const { return m_points; } + std::vector m_points; + std::vector m_elements; + int m_segments; + VPointF mStartPoint; + bool mNewSegment; }; vcow_ptr d; }; -inline bool VPath::isEmpty()const +inline bool VPath::isEmpty() const { return d->isEmpty(); } @@ -122,26 +125,28 @@ inline int VPath::segments() const inline float VPath::length() const { - //TODO re-calculate when there is a change + // TODO re-calculate when there is a change return d->length(); } -inline void VPath::cubicTo(const VPointF &c1, const VPointF &c2, const VPointF &e) +inline void VPath::cubicTo(const VPointF &c1, const VPointF &c2, + const VPointF &e) { d.write().cubicTo(c1, c2, e); } inline void VPath::lineTo(float x, float y) { - lineTo(VPointF(x,y)); + lineTo(VPointF(x, y)); } inline void VPath::moveTo(float x, float y) { - moveTo(VPointF(x,y)); + moveTo(VPointF(x, y)); } -inline void VPath::cubicTo(float c1x, float c1y, float c2x, float c2y, float ex, float ey) +inline void VPath::cubicTo(float c1x, float c1y, float c2x, float c2y, float ex, + float ey) { cubicTo(VPointF(c1x, c1y), VPointF(c2x, c2y), VPointF(ex, ey)); } @@ -151,7 +156,8 @@ inline void VPath::transform(const VMatrix &m) d.write().transform(m); } -inline void VPath::arcTo(const VRectF &rect, float startAngle, float sweepLength, bool forceMoveTo) +inline void VPath::arcTo(const VRectF &rect, float startAngle, + float sweepLength, bool forceMoveTo) { d.write().arcTo(rect, startAngle, sweepLength, forceMoveTo); } @@ -161,12 +167,14 @@ inline void VPath::addRect(const VRectF &rect, VPath::Direction dir) d.write().addRect(rect, dir); } -inline void VPath::addRoundRect(const VRectF &rect, float rx, float ry, VPath::Direction dir) +inline void VPath::addRoundRect(const VRectF &rect, float rx, float ry, + VPath::Direction dir) { - d.write().addRoundRect(rect, rx, ry, dir); + d.write().addRoundRect(rect, rx, ry, dir); } -inline void VPath::addCircle(float cx, float cy, float radius, VPath::Direction dir) +inline void VPath::addCircle(float cx, float cy, float radius, + VPath::Direction dir) { d.write().addCircle(cx, cy, radius, dir); } @@ -176,20 +184,20 @@ inline void VPath::addOval(const VRectF &rect, VPath::Direction dir) d.write().addOval(rect, dir); } -inline void VPath::addPolystar(float points, float innerRadius, float outerRadius, - float innerRoundness, float outerRoundness, - float startAngle, float cx, float cy, VPath::Direction dir) +inline void VPath::addPolystar(float points, float innerRadius, + float outerRadius, float innerRoundness, + float outerRoundness, float startAngle, float cx, + float cy, VPath::Direction dir) { - d.write().addPolystar(points, innerRadius, outerRadius, - innerRoundness, outerRoundness, - startAngle, cx, cy, dir); + d.write().addPolystar(points, innerRadius, outerRadius, innerRoundness, + outerRoundness, startAngle, cx, cy, dir); } inline void VPath::addPolygon(float points, float radius, float roundness, - float startAngle, float cx, float cy, VPath::Direction dir) + float startAngle, float cx, float cy, + VPath::Direction dir) { - d.write().addPolygon(points, radius, roundness, - startAngle, cx, cy, dir); + d.write().addPolygon(points, radius, roundness, startAngle, cx, cy, dir); } inline const std::vector &VPath::elements() const @@ -204,4 +212,4 @@ inline const std::vector &VPath::points() const V_END_NAMESPACE -#endif // VPATH_H +#endif // VPATH_H diff --git a/src/vector/vpathmesure.cpp b/src/vector/vpathmesure.cpp index 835f0f8..5e93f8f 100644 --- a/src/vector/vpathmesure.cpp +++ b/src/vector/vpathmesure.cpp @@ -1,28 +1,28 @@ -#include"vpathmesure.h" -#include"vbezier.h" -#include"vdasher.h" +#include "vpathmesure.h" +#include "vbezier.h" +#include "vdasher.h" V_BEGIN_NAMESPACE void VPathMesure::setOffset(float sp, float ep) { - startOffset = sp; - endOffset = ep; + startOffset = sp; + endOffset = ep; } VPath VPathMesure::trim(const VPath &path) { - if (vCompare(startOffset, 0.0f) && (vCompare(endOffset, 1.0f))) return path; + if (vCompare(startOffset, 0.0f) && (vCompare(endOffset, 1.0f))) return path; - float len = path.length(); - float sg = len * startOffset; - float eg = len * (1.0f - endOffset); - len = len - (sg + eg); + float len = path.length(); + float sg = len * startOffset; + float eg = len * (1.0f - endOffset); + len = len - (sg + eg); - float array[5] = { 0.0f, sg, len, 1000, 0.0f }; - VDasher dasher(array, 5); + float array[5] = {0.0f, sg, len, 1000, 0.0f}; + VDasher dasher(array, 5); - return dasher.dashed(path); + return dasher.dashed(path); } V_END_NAMESPACE diff --git a/src/vector/vpathmesure.h b/src/vector/vpathmesure.h index 6e507c8..61b1d34 100644 --- a/src/vector/vpathmesure.h +++ b/src/vector/vpathmesure.h @@ -5,16 +5,16 @@ V_BEGIN_NAMESPACE -class VPathMesure -{ +class VPathMesure { public: - void setOffset(float sp, float ep); - VPath trim(const VPath &path); + void setOffset(float sp, float ep); + VPath trim(const VPath &path); + private: - float startOffset { 0.0f }; - float endOffset { 1.0f }; + float startOffset{0.0f}; + float endOffset{1.0f}; }; V_END_NAMESPACE -#endif // VPATHMESURE_H +#endif // VPATHMESURE_H diff --git a/src/vector/vpoint.h b/src/vector/vpoint.h index 3d47514..3c94ab0 100644 --- a/src/vector/vpoint.h +++ b/src/vector/vpoint.h @@ -1,151 +1,188 @@ #ifndef VPOINT_H #define VPOINT_H -#include"vglobal.h" +#include "vglobal.h" V_BEGIN_NAMESPACE -class VPointF -{ +class VPointF { public: - constexpr inline VPointF() noexcept :mx(0), my(0){} - constexpr inline VPointF(float x, float y) noexcept :mx(x), my(y){} - constexpr inline float x() const noexcept {return mx;} - constexpr inline float y() const noexcept {return my;} - inline float& rx() noexcept {return mx;} - inline float& ry() noexcept {return my;} - inline void setX(float x) {mx = x;} - inline void setY(float y) {my = y;} - inline VPointF operator-() noexcept { return VPointF(-mx, -my); } - inline VPointF &operator+=(const VPointF &p) noexcept; - inline VPointF &operator-=(const VPointF &p) noexcept; - friend const VPointF operator+(const VPointF & p1, const VPointF & p2) { - return VPointF(p1.mx + p2.mx , p1.my + p2.my); + constexpr inline VPointF() noexcept : mx(0), my(0) {} + constexpr inline VPointF(float x, float y) noexcept : mx(x), my(y) {} + constexpr inline float x() const noexcept { return mx; } + constexpr inline float y() const noexcept { return my; } + inline float & rx() noexcept { return mx; } + inline float & ry() noexcept { return my; } + inline void setX(float x) { mx = x; } + inline void setY(float y) { my = y; } + inline VPointF operator-() noexcept { return VPointF(-mx, -my); } + inline VPointF & operator+=(const VPointF &p) noexcept; + inline VPointF & operator-=(const VPointF &p) noexcept; + friend const VPointF operator+(const VPointF &p1, const VPointF &p2) + { + return VPointF(p1.mx + p2.mx, p1.my + p2.my); } - inline friend const bool fuzzyCompare(const VPointF & p1, const VPointF & p2); - inline friend VDebug& operator<<(VDebug& os, const VPointF& o); + inline friend const bool fuzzyCompare(const VPointF &p1, const VPointF &p2); + inline friend VDebug & operator<<(VDebug &os, const VPointF &o); - friend inline VPointF operator-(const VPointF &p1, const VPointF &p2); + friend inline VPointF operator-(const VPointF &p1, const VPointF &p2); friend inline const VPointF operator*(const VPointF &, float val); friend inline const VPointF operator*(float val, const VPointF &); friend inline const VPointF operator/(const VPointF &, float val); friend inline const VPointF operator/(float val, const VPointF &); + private: float mx; float my; }; -inline const bool fuzzyCompare(const VPointF & p1, const VPointF & p2) +inline const bool fuzzyCompare(const VPointF &p1, const VPointF &p2) { - return (vCompare(p1.mx , p2.mx) && vCompare(p1.my , p2.my)); + return (vCompare(p1.mx, p2.mx) && vCompare(p1.my, p2.my)); } - inline VPointF operator-(const VPointF &p1, const VPointF &p2) { - return VPointF(p1.mx-p2.mx, p1.my-p2.my); + return VPointF(p1.mx - p2.mx, p1.my - p2.my); } inline const VPointF operator*(const VPointF &p, float c) -{ return VPointF(p.mx*c, p.my*c); } +{ + return VPointF(p.mx * c, p.my * c); +} inline const VPointF operator*(float c, const VPointF &p) -{ return VPointF(p.mx*c, p.my*c); } +{ + return VPointF(p.mx * c, p.my * c); +} inline const VPointF operator/(const VPointF &p, float c) -{ return VPointF(p.mx/c, p.my/c); } +{ + return VPointF(p.mx / c, p.my / c); +} inline const VPointF operator/(float c, const VPointF &p) -{ return VPointF(p.mx/c, p.my/c); } +{ + return VPointF(p.mx / c, p.my / c); +} -inline VDebug& operator<<(VDebug& os, const VPointF& o) +inline VDebug &operator<<(VDebug &os, const VPointF &o) { - os<<"{P "< -#include"vdebug.h" -#include"vtaskqueue.h" -#include +#include "vraster.h" +#include +#include +#include "v_ft_raster.h" +#include "v_ft_stroker.h" +#include "vdebug.h" +#include "vmatrix.h" +#include "vpath.h" +#include "vtaskqueue.h" V_BEGIN_NAMESPACE -struct FTOutline -{ +struct FTOutline { public: - FTOutline():mMemory(nullptr){} - ~FTOutline(){delete[] mMemory;} - void releaseMemory() { - if (mMemory) delete [] mMemory; + FTOutline() : mMemory(nullptr) {} + ~FTOutline() { delete[] mMemory; } + void releaseMemory() + { + if (mMemory) delete[] mMemory; mMemory = nullptr; mPointSize = 0; mSegmentSize = 0; @@ -31,16 +31,16 @@ public: void close(); void end(); void transform(const VMatrix &m); - SW_FT_Outline ft; - SW_FT_Vector *mMemory{nullptr}; - int mPointSize{0}; - int mSegmentSize{0}; - bool closed{false}; - SW_FT_Stroker_LineCap ftCap; - SW_FT_Stroker_LineJoin ftJoin; - SW_FT_Fixed ftWidth; - SW_FT_Fixed ftMeterLimit; - SW_FT_Bool ftClosed; + SW_FT_Outline ft; + SW_FT_Vector * mMemory{nullptr}; + int mPointSize{0}; + int mSegmentSize{0}; + bool closed{false}; + SW_FT_Stroker_LineCap ftCap; + SW_FT_Stroker_LineJoin ftJoin; + SW_FT_Fixed ftWidth; + SW_FT_Fixed ftMeterLimit; + SW_FT_Bool ftClosed; }; void FTOutline::reset() @@ -52,19 +52,19 @@ void FTOutline::reset() void FTOutline::grow(int points, int segments) { reset(); - if (mPointSize >= points && mSegmentSize >= segments) - return; + if (mPointSize >= points && mSegmentSize >= segments) return; // release old memory releaseMemory(); - //update book keeping + // update book keeping mPointSize = points; mSegmentSize = segments; int point_size = (points + segments); int contour_size = ((sizeof(short) * segments) / sizeof(SW_FT_Vector)) + 1; - int tag_size = ((sizeof(char) * (points + segments)) / sizeof(SW_FT_Vector)) + 1; + int tag_size = + ((sizeof(char) * (points + segments)) / sizeof(SW_FT_Vector)) + 1; /* * Optimization, instead of allocating 3 different buffer @@ -80,13 +80,13 @@ void FTOutline::grow(int points, int segments) void FTOutline::convert(const VPath &path) { const std::vector &elements = path.elements(); - const std::vector &points = path.points(); + const std::vector & points = path.points(); grow(points.size(), path.segments()); int index = 0; - for(auto element : elements) { - switch (element){ + for (auto element : elements) { + switch (element) { case VPath::Element::MoveTo: moveTo(points[index]); index++; @@ -96,8 +96,8 @@ void FTOutline::convert(const VPath &path) index++; break; case VPath::Element::CubicTo: - cubicTo(points[index], points[index+1], points[index+2]); - index = index+3; + cubicTo(points[index], points[index + 1], points[index + 2]); + index = index + 3; break; case VPath::Element::Close: close(); @@ -109,48 +109,46 @@ void FTOutline::convert(const VPath &path) end(); } -void FTOutline::convert(CapStyle cap, JoinStyle join, - float width, float meterLimit) +void FTOutline::convert(CapStyle cap, JoinStyle join, float width, + float meterLimit) { - ftClosed = (SW_FT_Bool) closed; + ftClosed = (SW_FT_Bool)closed; - // map strokeWidth to freetype. It uses as the radius of the pen not the diameter - width = width/2.0; + // map strokeWidth to freetype. It uses as the radius of the pen not the + // diameter + width = width / 2.0; // convert to freetype co-ordinate - //IMP: stroker takes radius in 26.6 co-ordinate - ftWidth = SW_FT_Fixed(width * (1<<6)); - //IMP: stroker takes meterlimit in 16.16 co-ordinate - ftMeterLimit = SW_FT_Fixed(meterLimit * (1<<16)); + // IMP: stroker takes radius in 26.6 co-ordinate + ftWidth = SW_FT_Fixed(width * (1 << 6)); + // IMP: stroker takes meterlimit in 16.16 co-ordinate + ftMeterLimit = SW_FT_Fixed(meterLimit * (1 << 16)); // map to freetype capstyle - switch (cap) - { - case CapStyle::Square: - ftCap = SW_FT_STROKER_LINECAP_SQUARE; - break; - case CapStyle::Round: - ftCap = SW_FT_STROKER_LINECAP_ROUND; - break; - default: - ftCap = SW_FT_STROKER_LINECAP_BUTT; - break; - } - switch (join) - { - case JoinStyle::Bevel: - ftJoin = SW_FT_STROKER_LINEJOIN_BEVEL; - break; - case JoinStyle::Round: - ftJoin = SW_FT_STROKER_LINEJOIN_ROUND; - break; - default: - ftJoin = SW_FT_STROKER_LINEJOIN_MITER; - break; - } + switch (cap) { + case CapStyle::Square: + ftCap = SW_FT_STROKER_LINECAP_SQUARE; + break; + case CapStyle::Round: + ftCap = SW_FT_STROKER_LINECAP_ROUND; + break; + default: + ftCap = SW_FT_STROKER_LINECAP_BUTT; + break; + } + switch (join) { + case JoinStyle::Bevel: + ftJoin = SW_FT_STROKER_LINEJOIN_BEVEL; + break; + case JoinStyle::Round: + ftJoin = SW_FT_STROKER_LINEJOIN_ROUND; + break; + default: + ftJoin = SW_FT_STROKER_LINEJOIN_MITER; + break; + } } - -#define TO_FT_COORD(x) ((x) * 64) // to freetype 26.6 coordinate. +#define TO_FT_COORD(x) ((x)*64) // to freetype 26.6 coordinate. void FTOutline::moveTo(const VPointF &pt) { @@ -174,7 +172,8 @@ void FTOutline::lineTo(const VPointF &pt) closed = false; } -void FTOutline::cubicTo(const VPointF &cp1, const VPointF &cp2, const VPointF ep) +void FTOutline::cubicTo(const VPointF &cp1, const VPointF &cp2, + const VPointF ep) { ft.points[ft.n_points].x = TO_FT_COORD(cp1.x()); ft.points[ft.n_points].y = TO_FT_COORD(cp1.y()); @@ -222,58 +221,54 @@ void FTOutline::end() } } -struct SpanInfo -{ - VRle::Span *spans; - int size; +struct SpanInfo { + VRle::Span *spans; + int size; }; -static void -rleGenerationCb( int count, const SW_FT_Span* spans,void *user) +static void rleGenerationCb(int count, const SW_FT_Span *spans, void *user) { - VRle *rle = (VRle *) user; - VRle::Span *rleSpan = (VRle::Span *)spans; - rle->addSpan(rleSpan, count); + VRle * rle = (VRle *)user; + VRle::Span *rleSpan = (VRle::Span *)spans; + rle->addSpan(rleSpan, count); } -struct RleTask -{ - RleTask() { - receiver = sender.get_future(); - } - std::promise sender; - std::future receiver; - bool stroke; - VPath path; - FillRule fillRule; - CapStyle cap; - JoinStyle join; - float width; - float meterLimit; - VRle operator()(FTOutline &outRef, SW_FT_Stroker &stroker); +struct RleTask { + RleTask() { receiver = sender.get_future(); } + std::promise sender; + std::future receiver; + bool stroke; + VPath path; + FillRule fillRule; + CapStyle cap; + JoinStyle join; + float width; + float meterLimit; + VRle operator()(FTOutline &outRef, SW_FT_Stroker &stroker); }; VRle RleTask::operator()(FTOutline &outRef, SW_FT_Stroker &stroker) { - if (stroke) { //Stroke Task + if (stroke) { // Stroke Task outRef.convert(path); outRef.convert(cap, join, width, meterLimit); - uint points,contors; + uint points, contors; - SW_FT_Stroker_Set(stroker, outRef.ftWidth, outRef.ftCap, outRef.ftJoin, outRef.ftMeterLimit); + SW_FT_Stroker_Set(stroker, outRef.ftWidth, outRef.ftCap, outRef.ftJoin, + outRef.ftMeterLimit); SW_FT_Stroker_ParseOutline(stroker, &outRef.ft, !outRef.ftClosed); - SW_FT_Stroker_GetCounts(stroker,&points, &contors); + SW_FT_Stroker_GetCounts(stroker, &points, &contors); FTOutline strokeOutline; strokeOutline.grow(points, contors); SW_FT_Stroker_Export(stroker, &strokeOutline.ft); - VRle rle; + VRle rle; SW_FT_Raster_Params params; - params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA ; + params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA; params.gray_spans = &rleGenerationCb; params.user = &rle; params.source = &strokeOutline; @@ -281,7 +276,7 @@ VRle RleTask::operator()(FTOutline &outRef, SW_FT_Stroker &stroker) sw_ft_grays_raster.raster_render(nullptr, ¶ms); return rle; - } else { //Fill Task + } else { // Fill Task outRef.convert(path); int fillRuleFlag = SW_FT_OUTLINE_NONE; switch (fillRule) { @@ -292,11 +287,11 @@ VRle RleTask::operator()(FTOutline &outRef, SW_FT_Stroker &stroker) fillRuleFlag = SW_FT_OUTLINE_NONE; break; } - outRef.ft.flags = fillRuleFlag; - VRle rle; + outRef.ft.flags = fillRuleFlag; + VRle rle; SW_FT_Raster_Params params; - params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA ; + params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA; params.gray_spans = &rleGenerationCb; params.user = &rle; params.source = &outRef.ft; @@ -307,16 +302,17 @@ VRle RleTask::operator()(FTOutline &outRef, SW_FT_Stroker &stroker) } class RleTaskScheduler { - const unsigned _count{std::thread::hardware_concurrency()}; - std::vector _threads; + const unsigned _count{std::thread::hardware_concurrency()}; + std::vector _threads; std::vector> _q{_count}; - std::atomic _index{0}; + std::atomic _index{0}; - void run(unsigned i) { + void run(unsigned i) + { /* * initalize per thread objects. */ - FTOutline outlineRef; + FTOutline outlineRef; SW_FT_Stroker stroker; SW_FT_Stroker_New(&stroker); @@ -333,26 +329,27 @@ class RleTaskScheduler { delete task; } - //cleanup + // cleanup SW_FT_Stroker_Done(stroker); } public: - RleTaskScheduler() { + RleTaskScheduler() + { for (unsigned n = 0; n != _count; ++n) { _threads.emplace_back([&, n] { run(n); }); } } - ~RleTaskScheduler() { - for (auto& e : _q) - e.done(); + ~RleTaskScheduler() + { + for (auto &e : _q) e.done(); - for (auto& e : _threads) - e.join(); + for (auto &e : _threads) e.join(); } - std::future async(RleTask *task) { + std::future async(RleTask *task) + { auto receiver = std::move(task->receiver); auto i = _index++; @@ -365,11 +362,9 @@ public: return receiver; } - std::future strokeRle(const VPath &path, - CapStyle cap, - JoinStyle join, - float width, - float meterLimit) { + std::future strokeRle(const VPath &path, CapStyle cap, JoinStyle join, + float width, float meterLimit) + { RleTask *task = new RleTask(); task->stroke = true; task->path = path; @@ -380,7 +375,8 @@ public: return async(task); } - std::future fillRle(const VPath &path, FillRule fillRule) { + std::future fillRle(const VPath &path, FillRule fillRule) + { RleTask *task = new RleTask(); task->path = path; task->fillRule = fillRule; @@ -391,16 +387,12 @@ public: static RleTaskScheduler raster_scheduler; -VRaster::VRaster() -{ -} +VRaster::VRaster() {} -VRaster::~VRaster() -{ -} +VRaster::~VRaster() {} -std::future -VRaster::generateFillInfo(const VPath &path, FillRule fillRule) +std::future VRaster::generateFillInfo(const VPath &path, + FillRule fillRule) { if (path.isEmpty()) { std::promise promise; @@ -410,9 +402,9 @@ VRaster::generateFillInfo(const VPath &path, FillRule fillRule) return raster_scheduler.fillRle(path, fillRule); } -std::future -VRaster::generateStrokeInfo(const VPath &path, CapStyle cap, JoinStyle join, - float width, float meterLimit) +std::future VRaster::generateStrokeInfo(const VPath &path, CapStyle cap, + JoinStyle join, float width, + float meterLimit) { if (path.isEmpty()) { std::promise promise; diff --git a/src/vector/vraster.h b/src/vector/vraster.h index a2c1ad8..178786c 100644 --- a/src/vector/vraster.h +++ b/src/vector/vraster.h @@ -1,7 +1,7 @@ #ifndef VRASTER_H #define VRASTER_H -#include"vrle.h" -#include +#include +#include "vrle.h" V_BEGIN_NAMESPACE @@ -9,8 +9,7 @@ struct FTOutline; class VPath; struct VRasterPrivate; -class VRaster -{ +class VRaster { public: ~VRaster(); static VRaster &instance() @@ -19,17 +18,20 @@ public: return Singleton; } VRaster(const VRaster &other) = delete; - VRaster(VRaster&&) = delete; - VRaster& operator=(VRaster const&) = delete; - VRaster& operator=(VRaster &&) = delete; + VRaster(VRaster &&) = delete; + VRaster &operator=(VRaster const &) = delete; + VRaster &operator=(VRaster &&) = delete; + + std::future generateFillInfo(const VPath &path, + FillRule fillRule = FillRule::Winding); + std::future generateStrokeInfo(const VPath &path, CapStyle cap, + JoinStyle join, float width, + float meterLimit); - std::future generateFillInfo(const VPath &path, FillRule fillRule = FillRule::Winding); - std::future generateStrokeInfo(const VPath &path, CapStyle cap, JoinStyle join, - float width, float meterLimit); private: VRaster(); }; V_END_NAMESPACE -#endif // VRASTER_H +#endif // VRASTER_H diff --git a/src/vector/vrect.h b/src/vector/vrect.h index c16ecab..0a2efdd 100644 --- a/src/vector/vrect.h +++ b/src/vector/vrect.h @@ -1,39 +1,41 @@ #ifndef VRECT_H #define VRECT_H -#include"vglobal.h" -#include"vpoint.h" +#include "vglobal.h" +#include "vpoint.h" V_BEGIN_NAMESPACE -class VRect -{ +class VRect { public: - V_CONSTEXPR VRect(): x1(0), y1(0), x2(-1), y2(-1) {} - V_CONSTEXPR VRect(int left, int top, int width, int height); + V_CONSTEXPR VRect() : x1(0), y1(0), x2(-1), y2(-1) {} + V_CONSTEXPR VRect(int left, int top, int width, int height); V_CONSTEXPR inline bool isEmpty() const; V_CONSTEXPR inline bool isNull() const; - V_CONSTEXPR inline int left() const ; - V_CONSTEXPR inline int top() const ; - V_CONSTEXPR inline int right() const ; - V_CONSTEXPR inline int bottom() const ; - V_CONSTEXPR inline int width() const ; - V_CONSTEXPR inline int height() const ; - V_CONSTEXPR inline int x() const ; - V_CONSTEXPR inline int y() const ; - inline void setLeft(int l) {x1 = l;} - inline void setTop(int t) {y1 = t;} - inline void setRight(int r) {x2 = r;} - inline void setBottom(int b) {y2 = b;} - inline void setWidth(int w) {x2 = x1 + w;} - inline void setHeight(int h) {y2 = y1 + h;} - inline VRect translated(int dx, int dy) const ; - inline void translate(int dx, int dy); - inline bool contains(const VRect &r, bool proper = false) const; - inline bool intersects(const VRect &r); - friend V_CONSTEXPR inline bool operator==(const VRect &, const VRect &) noexcept; - friend V_CONSTEXPR inline bool operator!=(const VRect &, const VRect &) noexcept; - friend VDebug& operator<<(VDebug& os, const VRect& o); + V_CONSTEXPR inline int left() const; + V_CONSTEXPR inline int top() const; + V_CONSTEXPR inline int right() const; + V_CONSTEXPR inline int bottom() const; + V_CONSTEXPR inline int width() const; + V_CONSTEXPR inline int height() const; + V_CONSTEXPR inline int x() const; + V_CONSTEXPR inline int y() const; + inline void setLeft(int l) { x1 = l; } + inline void setTop(int t) { y1 = t; } + inline void setRight(int r) { x2 = r; } + inline void setBottom(int b) { y2 = b; } + inline void setWidth(int w) { x2 = x1 + w; } + inline void setHeight(int h) { y2 = y1 + h; } + inline VRect translated(int dx, int dy) const; + inline void translate(int dx, int dy); + inline bool contains(const VRect &r, bool proper = false) const; + inline bool intersects(const VRect &r); + friend V_CONSTEXPR inline bool operator==(const VRect &, + const VRect &) noexcept; + friend V_CONSTEXPR inline bool operator!=(const VRect &, + const VRect &) noexcept; + friend VDebug & operator<<(VDebug &os, const VRect &o); + private: int x1; int y1; @@ -43,55 +45,78 @@ private: inline bool VRect::intersects(const VRect &r) { - return (right() > r.left() && left() < r.right() && - bottom() > r.top() && top() < r.bottom()); + return (right() > r.left() && left() < r.right() && bottom() > r.top() && + top() < r.bottom()); } -inline VDebug& operator<<(VDebug& os, const VRect& o) +inline VDebug &operator<<(VDebug &os, const VRect &o) { - os<<"{R "< x2 || y1 > y2; } +{ + return x1 > x2 || y1 > y2; +} V_CONSTEXPR inline bool VRect::isNull() const -{ return (((x2-x1) == 0) || ((y2 - y1) == 0)); } +{ + return (((x2 - x1) == 0) || ((y2 - y1) == 0)); +} V_CONSTEXPR inline int VRect::x() const -{ return x1; } +{ + return x1; +} V_CONSTEXPR inline int VRect::y() const -{ return y1; } +{ + return y1; +} V_CONSTEXPR inline int VRect::left() const -{ return x1; } +{ + return x1; +} V_CONSTEXPR inline int VRect::top() const -{ return y1; } +{ + return y1; +} V_CONSTEXPR inline int VRect::right() const -{ return x2; } +{ + return x2; +} V_CONSTEXPR inline int VRect::bottom() const -{ return y2; } +{ + return y2; +} V_CONSTEXPR inline int VRect::width() const -{ return x2 - x1; } +{ + return x2 - x1; +} V_CONSTEXPR inline int VRect::height() const -{ return y2 - y1; } +{ + return y2 - y1; +} inline VRect VRect::translated(int dx, int dy) const -{ return VRect(x1+dx, y1+dy, x2-x1, y2-y1); } +{ + return VRect(x1 + dx, y1 + dy, x2 - x1, y2 - y1); +} inline void VRect::translate(int dx, int dy) { @@ -103,51 +128,59 @@ inline void VRect::translate(int dx, int dy) inline bool VRect::contains(const VRect &r, bool proper) const { if (!proper) { - if ((x1 <= r.x1) && - (x2 >= r.x2) && - (y1 <= r.y1) && - (y2 >= r.y2)) + if ((x1 <= r.x1) && (x2 >= r.x2) && (y1 <= r.y1) && (y2 >= r.y2)) return true; return false; - }else { - if ((x1 < r.x1) && - (x2 > r.x2) && - (y1 < r.y1) && - (y2 > r.y2)) + } else { + if ((x1 < r.x1) && (x2 > r.x2) && (y1 < r.y1) && (y2 > r.y2)) return true; return false; } - } -V_CONSTEXPR inline VRect::VRect(int left, int top, int width, int height): - x1(left), y1(top), x2(width + left), y2(height + top){} - -class VRectF +V_CONSTEXPR inline VRect::VRect(int left, int top, int width, int height) + : x1(left), y1(top), x2(width + left), y2(height + top) { +} + +class VRectF { public: - V_CONSTEXPR VRectF(): x1(0), y1(0), x2(-1), y2(-1) {} - VRectF(float left, float top, float width, float height){ - x1 = left; y1 = top; x2 = x1 + width; y2 = y1 + height; + V_CONSTEXPR VRectF() : x1(0), y1(0), x2(-1), y2(-1) {} + VRectF(float left, float top, float width, float height) + { + x1 = left; + y1 = top; + x2 = x1 + width; + y2 = y1 + height; + } + + V_CONSTEXPR inline bool isEmpty() const; + V_CONSTEXPR inline bool isNull() const; + V_CONSTEXPR inline float left() const; + V_CONSTEXPR inline float top() const; + V_CONSTEXPR inline float right() const; + V_CONSTEXPR inline float bottom() const; + V_CONSTEXPR inline float width() const; + V_CONSTEXPR inline float height() const; + V_CONSTEXPR inline float x() const; + V_CONSTEXPR inline float y() const; + V_CONSTEXPR inline VPointF center() const + { + return VPointF(x1 + (x2 - x1) / 2.f, y1 + (y2 - y1) / 2.f); + } + inline void setLeft(float l) { x1 = l; } + inline void setTop(float t) { y1 = t; } + inline void setRight(float r) { x2 = r; } + inline void setBottom(float b) { y2 = b; } + inline void setWidth(float w) { x2 = x1 + w; } + inline void setHeight(float h) { y2 = y1 + h; } + inline void translate(float dx, float dy) + { + x1 -= dx; + x2 -= dx; + y1 -= dx; + y2 -= dx; } - V_CONSTEXPR inline bool isEmpty() const; - V_CONSTEXPR inline bool isNull() const; - V_CONSTEXPR inline float left() const ; - V_CONSTEXPR inline float top() const ; - V_CONSTEXPR inline float right() const ; - V_CONSTEXPR inline float bottom() const ; - V_CONSTEXPR inline float width() const ; - V_CONSTEXPR inline float height() const ; - V_CONSTEXPR inline float x() const ; - V_CONSTEXPR inline float y() const ; - V_CONSTEXPR inline VPointF center() const {return VPointF(x1 + (x2-x1)/2.f , y1 + (y2-y1)/2.f);} - inline void setLeft(float l) {x1 = l;} - inline void setTop(float t) {y1 = t;} - inline void setRight(float r) {x2 = r;} - inline void setBottom(float b) {y2 = b;} - inline void setWidth(float w) {x2 = x1 + w;} - inline void setHeight(float h) {y2 = y1 + h;} - inline void translate(float dx, float dy) {x1 -= dx; x2 -= dx; y1 -= dx; y2 -= dx;} private: float x1; float y1; @@ -156,33 +189,53 @@ private: }; V_CONSTEXPR inline bool VRectF::isEmpty() const -{ return x1 > x2 || y1 > y2; } +{ + return x1 > x2 || y1 > y2; +} V_CONSTEXPR inline bool VRectF::isNull() const -{ return (((x2-x1) == 0) || ((y2 - y1) == 0)); } +{ + return (((x2 - x1) == 0) || ((y2 - y1) == 0)); +} V_CONSTEXPR inline float VRectF::x() const -{ return x1; } +{ + return x1; +} V_CONSTEXPR inline float VRectF::y() const -{ return y1; } +{ + return y1; +} V_CONSTEXPR inline float VRectF::left() const -{ return x1; } +{ + return x1; +} V_CONSTEXPR inline float VRectF::top() const -{ return y1; } +{ + return y1; +} V_CONSTEXPR inline float VRectF::right() const -{ return x2; } +{ + return x2; +} V_CONSTEXPR inline float VRectF::bottom() const -{ return y2; } +{ + return y2; +} V_CONSTEXPR inline float VRectF::width() const -{ return x2 - x1; } +{ + return x2 - x1; +} V_CONSTEXPR inline float VRectF::height() const -{ return y2 - y1; } +{ + return y2 - y1; +} V_END_NAMESPACE -#endif // VRECT_H +#endif // VRECT_H diff --git a/src/vector/vregion.cpp b/src/vector/vregion.cpp index da81953..f482330 100644 --- a/src/vector/vregion.cpp +++ b/src/vector/vregion.cpp @@ -63,12 +63,11 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include +#include +#include #include #include -#include -#include - +#include #define critical_if_fail assert #define PIXMAN_EXPORT static @@ -80,88 +79,78 @@ typedef int pixman_bool_t; -typedef struct pixman_rectangle pixman_rectangle_t; +typedef struct pixman_rectangle pixman_rectangle_t; -typedef struct pixman_box box_type_t; -typedef struct pixman_region_data region_data_type_t; -typedef struct pixman_region region_type_t; -typedef int64_t overflow_int_t; +typedef struct pixman_box box_type_t; +typedef struct pixman_region_data region_data_type_t; +typedef struct pixman_region region_type_t; +typedef int64_t overflow_int_t; #define PREFIX(x) pixman_region##x #define PIXMAN_REGION_MAX INT32_MAX #define PIXMAN_REGION_MIN INT32_MIN - typedef struct { int x, y; } point_type_t; struct pixman_region_data { - long size; - long numRects; -/* box_type_t rects[size]; in memory but not explicitly declared */ + long size; + long numRects; + /* box_type_t rects[size]; in memory but not explicitly declared */ }; -struct pixman_rectangle -{ - int32_t x, y; +struct pixman_rectangle { + int32_t x, y; uint32_t width, height; }; -struct pixman_box -{ +struct pixman_box { int32_t x1, y1, x2, y2; }; -struct pixman_region -{ +struct pixman_region { box_type_t extents; - region_data_type_t *data; + region_data_type_t *data; }; -typedef enum -{ +typedef enum { PIXMAN_REGION_OUT, PIXMAN_REGION_IN, PIXMAN_REGION_PART } pixman_region_overlap_t; -static void -_pixman_log_error (const char *function, const char *message) +static void _pixman_log_error(const char *function, const char *message) { - fprintf (stderr, - "*** BUG ***\n" - "In %s: %s\n" - "Set a breakpoint on '_pixman_log_error' to debug\n\n", - function, message); + fprintf(stderr, + "*** BUG ***\n" + "In %s: %s\n" + "Set a breakpoint on '_pixman_log_error' to debug\n\n", + function, message); } - - #define PIXREGION_NIL(reg) ((reg)->data && !(reg)->data->numRects) /* not a region */ -#define PIXREGION_NAR(reg) ((reg)->data == pixman_broken_data) +#define PIXREGION_NAR(reg) ((reg)->data == pixman_broken_data) #define PIXREGION_NUMRECTS(reg) ((reg)->data ? (reg)->data->numRects : 1) #define PIXREGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0) #define PIXREGION_RECTS(reg) \ - ((reg)->data ? (box_type_t *)((reg)->data + 1) \ - : &(reg)->extents) + ((reg)->data ? (box_type_t *)((reg)->data + 1) : &(reg)->extents) #define PIXREGION_BOXPTR(reg) ((box_type_t *)((reg)->data + 1)) -#define PIXREGION_BOX(reg, i) (&PIXREGION_BOXPTR (reg)[i]) -#define PIXREGION_TOP(reg) PIXREGION_BOX (reg, (reg)->data->numRects) -#define PIXREGION_END(reg) PIXREGION_BOX (reg, (reg)->data->numRects - 1) +#define PIXREGION_BOX(reg, i) (&PIXREGION_BOXPTR(reg)[i]) +#define PIXREGION_TOP(reg) PIXREGION_BOX(reg, (reg)->data->numRects) +#define PIXREGION_END(reg) PIXREGION_BOX(reg, (reg)->data->numRects - 1) #define GOOD_RECT(rect) ((rect)->x1 < (rect)->x2 && (rect)->y1 < (rect)->y2) #define BAD_RECT(rect) ((rect)->x1 > (rect)->x2 || (rect)->y1 > (rect)->y2) #ifdef DEBUG -#define GOOD(reg) \ - do \ - { \ - if (!PREFIX (_selfcheck (reg))) \ - _pixman_log_error (FUNC, "Malformed region " # reg); \ +#define GOOD(reg) \ + do { \ + if (!PREFIX(_selfcheck(reg))) \ + _pixman_log_error(FUNC, "Malformed region " #reg); \ } while (0) #else @@ -170,23 +159,21 @@ _pixman_log_error (const char *function, const char *message) #endif -static const box_type_t PREFIX (_empty_box_) = { 0, 0, 0, 0 }; -static const region_data_type_t PREFIX (_empty_data_) = { 0, 0 }; -#if defined (__llvm__) && !defined (__clang__) -static const volatile region_data_type_t PREFIX (_broken_data_) = { 0, 0 }; +static const box_type_t PREFIX(_empty_box_) = {0, 0, 0, 0}; +static const region_data_type_t PREFIX(_empty_data_) = {0, 0}; +#if defined(__llvm__) && !defined(__clang__) +static const volatile region_data_type_t PREFIX(_broken_data_) = {0, 0}; #else -static const region_data_type_t PREFIX (_broken_data_) = { 0, 0 }; +static const region_data_type_t PREFIX(_broken_data_) = {0, 0}; #endif -static box_type_t *pixman_region_empty_box = - (box_type_t *)&PREFIX (_empty_box_); +static box_type_t *pixman_region_empty_box = (box_type_t *)&PREFIX(_empty_box_); static region_data_type_t *pixman_region_empty_data = - (region_data_type_t *)&PREFIX (_empty_data_); + (region_data_type_t *)&PREFIX(_empty_data_); static region_data_type_t *pixman_broken_data = - (region_data_type_t *)&PREFIX (_broken_data_); + (region_data_type_t *)&PREFIX(_broken_data_); -static pixman_bool_t -pixman_break (region_type_t *region); +static pixman_bool_t pixman_break(region_type_t *region); /* * The functions in this file implement the Region abstraction used extensively @@ -238,261 +225,204 @@ pixman_break (region_type_t *region); */ /* true iff two Boxes overlap */ -#define EXTENTCHECK(r1, r2) \ - (!( ((r1)->x2 <= (r2)->x1) || \ - ((r1)->x1 >= (r2)->x2) || \ - ((r1)->y2 <= (r2)->y1) || \ - ((r1)->y1 >= (r2)->y2) ) ) +#define EXTENTCHECK(r1, r2) \ + (!(((r1)->x2 <= (r2)->x1) || ((r1)->x1 >= (r2)->x2) || \ + ((r1)->y2 <= (r2)->y1) || ((r1)->y1 >= (r2)->y2))) /* true iff (x,y) is in Box */ -#define INBOX(r, x, y) \ - ( ((r)->x2 > x) && \ - ((r)->x1 <= x) && \ - ((r)->y2 > y) && \ - ((r)->y1 <= y) ) +#define INBOX(r, x, y) \ + (((r)->x2 > x) && ((r)->x1 <= x) && ((r)->y2 > y) && ((r)->y1 <= y)) /* true iff Box r1 contains Box r2 */ -#define SUBSUMES(r1, r2) \ - ( ((r1)->x1 <= (r2)->x1) && \ - ((r1)->x2 >= (r2)->x2) && \ - ((r1)->y1 <= (r2)->y1) && \ - ((r1)->y2 >= (r2)->y2) ) +#define SUBSUMES(r1, r2) \ + (((r1)->x1 <= (r2)->x1) && ((r1)->x2 >= (r2)->x2) && \ + ((r1)->y1 <= (r2)->y1) && ((r1)->y2 >= (r2)->y2)) -static size_t -PIXREGION_SZOF (size_t n) +static size_t PIXREGION_SZOF(size_t n) { size_t size = n * sizeof(box_type_t); - if (n > UINT32_MAX / sizeof(box_type_t)) - return 0; + if (n > UINT32_MAX / sizeof(box_type_t)) return 0; - if (sizeof(region_data_type_t) > UINT32_MAX - size) - return 0; + if (sizeof(region_data_type_t) > UINT32_MAX - size) return 0; return size + sizeof(region_data_type_t); } -static region_data_type_t * -alloc_data (size_t n) +static region_data_type_t *alloc_data(size_t n) { - size_t sz = PIXREGION_SZOF (n); + size_t sz = PIXREGION_SZOF(n); - if (!sz) - return NULL; + if (!sz) return NULL; - return (region_data_type_t *)malloc (sz); + return (region_data_type_t *)malloc(sz); } -#define FREE_DATA(reg) if ((reg)->data && (reg)->data->size) free ((reg)->data) +#define FREE_DATA(reg) \ + if ((reg)->data && (reg)->data->size) free((reg)->data) -#define RECTALLOC_BAIL(region, n, bail) \ - do \ - { \ - if (!(region)->data || \ - (((region)->data->numRects + (n)) > (region)->data->size)) \ - { \ - if (!pixman_rect_alloc (region, n)) \ - goto bail; \ - } \ +#define RECTALLOC_BAIL(region, n, bail) \ + do { \ + if (!(region)->data || \ + (((region)->data->numRects + (n)) > (region)->data->size)) { \ + if (!pixman_rect_alloc(region, n)) goto bail; \ + } \ } while (0) -#define RECTALLOC(region, n) \ - do \ - { \ - if (!(region)->data || \ - (((region)->data->numRects + (n)) > (region)->data->size)) \ - { \ - if (!pixman_rect_alloc (region, n)) { \ - return FALSE; \ - } \ - } \ +#define RECTALLOC(region, n) \ + do { \ + if (!(region)->data || \ + (((region)->data->numRects + (n)) > (region)->data->size)) { \ + if (!pixman_rect_alloc(region, n)) { \ + return FALSE; \ + } \ + } \ } while (0) -#define ADDRECT(next_rect, nx1, ny1, nx2, ny2) \ - do \ - { \ - next_rect->x1 = nx1; \ - next_rect->y1 = ny1; \ - next_rect->x2 = nx2; \ - next_rect->y2 = ny2; \ - next_rect++; \ - } \ - while (0) - -#define NEWRECT(region, next_rect, nx1, ny1, nx2, ny2) \ - do \ - { \ - if (!(region)->data || \ - ((region)->data->numRects == (region)->data->size)) \ - { \ - if (!pixman_rect_alloc (region, 1)) \ - return FALSE; \ - next_rect = PIXREGION_TOP (region); \ - } \ - ADDRECT (next_rect, nx1, ny1, nx2, ny2); \ - region->data->numRects++; \ - critical_if_fail (region->data->numRects <= region->data->size); \ +#define ADDRECT(next_rect, nx1, ny1, nx2, ny2) \ + do { \ + next_rect->x1 = nx1; \ + next_rect->y1 = ny1; \ + next_rect->x2 = nx2; \ + next_rect->y2 = ny2; \ + next_rect++; \ } while (0) -#define DOWNSIZE(reg, numRects) \ - do \ - { \ - if (((numRects) < ((reg)->data->size >> 1)) && \ - ((reg)->data->size > 50)) \ - { \ - region_data_type_t * new_data; \ - size_t data_size = PIXREGION_SZOF (numRects); \ - \ - if (!data_size) \ - { \ - new_data = NULL; \ - } \ - else \ - { \ - new_data = (region_data_type_t *) \ - realloc ((reg)->data, data_size); \ - } \ - \ - if (new_data) \ - { \ - new_data->size = (numRects); \ - (reg)->data = new_data; \ - } \ - } \ +#define NEWRECT(region, next_rect, nx1, ny1, nx2, ny2) \ + do { \ + if (!(region)->data || \ + ((region)->data->numRects == (region)->data->size)) { \ + if (!pixman_rect_alloc(region, 1)) return FALSE; \ + next_rect = PIXREGION_TOP(region); \ + } \ + ADDRECT(next_rect, nx1, ny1, nx2, ny2); \ + region->data->numRects++; \ + critical_if_fail(region->data->numRects <= region->data->size); \ } while (0) -PIXMAN_EXPORT pixman_bool_t -PREFIX (_equal) (region_type_t *reg1, region_type_t *reg2) +#define DOWNSIZE(reg, numRects) \ + do { \ + if (((numRects) < ((reg)->data->size >> 1)) && \ + ((reg)->data->size > 50)) { \ + region_data_type_t *new_data; \ + size_t data_size = PIXREGION_SZOF(numRects); \ + \ + if (!data_size) { \ + new_data = NULL; \ + } else { \ + new_data = \ + (region_data_type_t *)realloc((reg)->data, data_size); \ + } \ + \ + if (new_data) { \ + new_data->size = (numRects); \ + (reg)->data = new_data; \ + } \ + } \ + } while (0) + +PIXMAN_EXPORT pixman_bool_t PREFIX(_equal)(region_type_t *reg1, + region_type_t *reg2) { - int i; + int i; box_type_t *rects1; box_type_t *rects2; - if (reg1->extents.x1 != reg2->extents.x1) - return FALSE; + if (reg1->extents.x1 != reg2->extents.x1) return FALSE; - if (reg1->extents.x2 != reg2->extents.x2) - return FALSE; + if (reg1->extents.x2 != reg2->extents.x2) return FALSE; - if (reg1->extents.y1 != reg2->extents.y1) - return FALSE; + if (reg1->extents.y1 != reg2->extents.y1) return FALSE; - if (reg1->extents.y2 != reg2->extents.y2) - return FALSE; + if (reg1->extents.y2 != reg2->extents.y2) return FALSE; - if (PIXREGION_NUMRECTS (reg1) != PIXREGION_NUMRECTS (reg2)) - return FALSE; + if (PIXREGION_NUMRECTS(reg1) != PIXREGION_NUMRECTS(reg2)) return FALSE; - rects1 = PIXREGION_RECTS (reg1); - rects2 = PIXREGION_RECTS (reg2); + rects1 = PIXREGION_RECTS(reg1); + rects2 = PIXREGION_RECTS(reg2); - for (i = 0; i != PIXREGION_NUMRECTS (reg1); i++) - { - if (rects1[i].x1 != rects2[i].x1) - return FALSE; + for (i = 0; i != PIXREGION_NUMRECTS(reg1); i++) { + if (rects1[i].x1 != rects2[i].x1) return FALSE; - if (rects1[i].x2 != rects2[i].x2) - return FALSE; + if (rects1[i].x2 != rects2[i].x2) return FALSE; - if (rects1[i].y1 != rects2[i].y1) - return FALSE; + if (rects1[i].y1 != rects2[i].y1) return FALSE; - if (rects1[i].y2 != rects2[i].y2) - return FALSE; + if (rects1[i].y2 != rects2[i].y2) return FALSE; } return TRUE; } // returns true if both region intersects -PIXMAN_EXPORT pixman_bool_t -PREFIX (_intersects) (region_type_t *reg1, region_type_t *reg2) -{ - box_type_t *rects1 = PIXREGION_RECTS (reg1); - box_type_t *rects2 = PIXREGION_RECTS (reg2); - for (int i = 0; i != PIXREGION_NUMRECTS (reg1); i++) - { - for(int j = 0; j != PIXREGION_NUMRECTS (reg2); j++) - { - if (EXTENTCHECK(rects1 + i, rects2 + j)) - return TRUE; +PIXMAN_EXPORT pixman_bool_t PREFIX(_intersects)(region_type_t *reg1, + region_type_t *reg2) +{ + box_type_t *rects1 = PIXREGION_RECTS(reg1); + box_type_t *rects2 = PIXREGION_RECTS(reg2); + for (int i = 0; i != PIXREGION_NUMRECTS(reg1); i++) { + for (int j = 0; j != PIXREGION_NUMRECTS(reg2); j++) { + if (EXTENTCHECK(rects1 + i, rects2 + j)) return TRUE; } } return FALSE; } -int -PREFIX (_print) (region_type_t *rgn) +int PREFIX(_print)(region_type_t *rgn) { - int num, size; - int i; - box_type_t * rects; + int num, size; + int i; + box_type_t *rects; - num = PIXREGION_NUMRECTS (rgn); - size = PIXREGION_SIZE (rgn); - rects = PIXREGION_RECTS (rgn); + num = PIXREGION_NUMRECTS(rgn); + size = PIXREGION_SIZE(rgn); + rects = PIXREGION_RECTS(rgn); - fprintf (stderr, "num: %d size: %d\n", num, size); - fprintf (stderr, "extents: %d %d %d %d\n", - rgn->extents.x1, - rgn->extents.y1, - rgn->extents.x2, - rgn->extents.y2); + fprintf(stderr, "num: %d size: %d\n", num, size); + fprintf(stderr, "extents: %d %d %d %d\n", rgn->extents.x1, rgn->extents.y1, + rgn->extents.x2, rgn->extents.y2); - for (i = 0; i < num; i++) - { - fprintf (stderr, "%d %d %d %d \n", - rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2); + for (i = 0; i < num; i++) { + fprintf(stderr, "%d %d %d %d \n", rects[i].x1, rects[i].y1, rects[i].x2, + rects[i].y2); } - fprintf (stderr, "\n"); + fprintf(stderr, "\n"); - return(num); + return (num); } - -PIXMAN_EXPORT void -PREFIX (_init) (region_type_t *region) +PIXMAN_EXPORT void PREFIX(_init)(region_type_t *region) { region->extents = *pixman_region_empty_box; region->data = pixman_region_empty_data; } -PIXMAN_EXPORT pixman_bool_t -PREFIX (_union_rect) (region_type_t *dest, - region_type_t *source, - int x, - int y, - unsigned int width, - unsigned int height); -PIXMAN_EXPORT void -PREFIX (_init_rect) (region_type_t * region, - int x, - int y, - unsigned int width, - unsigned int height) +PIXMAN_EXPORT pixman_bool_t PREFIX(_union_rect)(region_type_t *dest, + region_type_t *source, int x, + int y, unsigned int width, + unsigned int height); +PIXMAN_EXPORT void PREFIX(_init_rect)(region_type_t *region, int x, int y, + unsigned int width, unsigned int height) { - PREFIX (_init) (region); - PREFIX (_union_rect)(region, region, x, y, width, height); + PREFIX(_init)(region); + PREFIX(_union_rect)(region, region, x, y, width, height); } -PIXMAN_EXPORT void -PREFIX (_fini) (region_type_t *region) +PIXMAN_EXPORT void PREFIX(_fini)(region_type_t *region) { - GOOD (region); - FREE_DATA (region); + GOOD(region); + FREE_DATA(region); } -PIXMAN_EXPORT int -PREFIX (_n_rects) (region_type_t *region) +PIXMAN_EXPORT int PREFIX(_n_rects)(region_type_t *region) { - return PIXREGION_NUMRECTS (region); + return PIXREGION_NUMRECTS(region); } -static pixman_bool_t -pixman_break (region_type_t *region) +static pixman_bool_t pixman_break(region_type_t *region) { - FREE_DATA (region); + FREE_DATA(region); region->extents = *pixman_region_empty_box; region->data = pixman_broken_data; @@ -500,60 +430,46 @@ pixman_break (region_type_t *region) return FALSE; } -static pixman_bool_t -pixman_rect_alloc (region_type_t * region, - int n) +static pixman_bool_t pixman_rect_alloc(region_type_t *region, int n) { region_data_type_t *data; - if (!region->data) - { - n++; - region->data = alloc_data (n); + if (!region->data) { + n++; + region->data = alloc_data(n); - if (!region->data) - return pixman_break (region); + if (!region->data) return pixman_break(region); - region->data->numRects = 1; - *PIXREGION_BOXPTR (region) = region->extents; - } - else if (!region->data->size) - { - region->data = alloc_data (n); + region->data->numRects = 1; + *PIXREGION_BOXPTR(region) = region->extents; + } else if (!region->data->size) { + region->data = alloc_data(n); - if (!region->data) - return pixman_break (region); + if (!region->data) return pixman_break(region); - region->data->numRects = 0; - } - else - { - size_t data_size; + region->data->numRects = 0; + } else { + size_t data_size; - if (n == 1) - { - n = region->data->numRects; - if (n > 500) /* XXX pick numbers out of a hat */ - n = 250; - } + if (n == 1) { + n = region->data->numRects; + if (n > 500) /* XXX pick numbers out of a hat */ + n = 250; + } - n += region->data->numRects; - data_size = PIXREGION_SZOF (n); + n += region->data->numRects; + data_size = PIXREGION_SZOF(n); - if (!data_size) - { - data = NULL; - } - else - { - data = (region_data_type_t *) - realloc (region->data, PIXREGION_SZOF (n)); - } + if (!data_size) { + data = NULL; + } else { + data = + (region_data_type_t *)realloc(region->data, PIXREGION_SZOF(n)); + } - if (!data) - return pixman_break (region); + if (!data) return pixman_break(region); - region->data = data; + region->data = data; } region->data->size = n; @@ -561,40 +477,36 @@ pixman_rect_alloc (region_type_t * region, return TRUE; } -PIXMAN_EXPORT pixman_bool_t -PREFIX (_copy) (region_type_t *dst, region_type_t *src) +PIXMAN_EXPORT pixman_bool_t PREFIX(_copy)(region_type_t *dst, + region_type_t *src) { - GOOD (dst); - GOOD (src); + GOOD(dst); + GOOD(src); - if (dst == src) - return TRUE; + if (dst == src) return TRUE; dst->extents = src->extents; - if (!src->data || !src->data->size) - { - FREE_DATA (dst); - dst->data = src->data; - return TRUE; + if (!src->data || !src->data->size) { + FREE_DATA(dst); + dst->data = src->data; + return TRUE; } - if (!dst->data || (dst->data->size < src->data->numRects)) - { - FREE_DATA (dst); + if (!dst->data || (dst->data->size < src->data->numRects)) { + FREE_DATA(dst); - dst->data = alloc_data (src->data->numRects); + dst->data = alloc_data(src->data->numRects); - if (!dst->data) - return pixman_break (dst); + if (!dst->data) return pixman_break(dst); - dst->data->size = src->data->numRects; + dst->data->size = src->data->numRects; } dst->data->numRects = src->data->numRects; - memmove ((char *)PIXREGION_BOXPTR (dst), (char *)PIXREGION_BOXPTR (src), - dst->data->numRects * sizeof(box_type_t)); + memmove((char *)PIXREGION_BOXPTR(dst), (char *)PIXREGION_BOXPTR(src), + dst->data->numRects * sizeof(box_type_t)); return TRUE; } @@ -621,21 +533,21 @@ PREFIX (_copy) (region_type_t *dst, region_type_t *src) * *----------------------------------------------------------------------- */ -static inline int -pixman_coalesce (region_type_t * region, /* Region to coalesce */ - int prev_start, /* Index of start of previous band */ - int cur_start) /* Index of start of current band */ +static inline int pixman_coalesce( + region_type_t *region, /* Region to coalesce */ + int prev_start, /* Index of start of previous band */ + int cur_start) /* Index of start of current band */ { - box_type_t *prev_box; /* Current box in previous band */ - box_type_t *cur_box; /* Current box in current band */ - int numRects; /* Number rectangles in both bands */ - int y2; /* Bottom of current band */ + box_type_t *prev_box; /* Current box in previous band */ + box_type_t *cur_box; /* Current box in current band */ + int numRects; /* Number rectangles in both bands */ + int y2; /* Bottom of current band */ /* * Figure out how many rectangles are in the band. */ numRects = cur_start - prev_start; - critical_if_fail (numRects == region->data->numRects - cur_start); + critical_if_fail(numRects == region->data->numRects - cur_start); if (!numRects) return cur_start; @@ -643,8 +555,8 @@ pixman_coalesce (region_type_t * region, /* Region to coalesce */ * The bands may only be coalesced if the bottom of the previous * matches the top scanline of the current. */ - prev_box = PIXREGION_BOX (region, prev_start); - cur_box = PIXREGION_BOX (region, cur_start); + prev_box = PIXREGION_BOX(region, prev_start); + cur_box = PIXREGION_BOX(region, cur_start); if (prev_box->y2 != cur_box->y1) return cur_start; /* @@ -655,16 +567,14 @@ pixman_coalesce (region_type_t * region, /* Region to coalesce */ */ y2 = cur_box->y2; - do - { - if ((prev_box->x1 != cur_box->x1) || (prev_box->x2 != cur_box->x2)) - return (cur_start); + do { + if ((prev_box->x1 != cur_box->x1) || (prev_box->x2 != cur_box->x2)) + return (cur_start); - prev_box++; - cur_box++; - numRects--; - } - while (numRects); + prev_box++; + cur_box++; + numRects--; + } while (numRects); /* * The bands may be merged, so set the bottom y of each box @@ -673,13 +583,11 @@ pixman_coalesce (region_type_t * region, /* Region to coalesce */ numRects = cur_start - prev_start; region->data->numRects -= numRects; - do - { - prev_box--; - prev_box->y2 = y2; - numRects--; - } - while (numRects); + do { + prev_box--; + prev_box->y2 = y2; + numRects--; + } while (numRects); return prev_start; } @@ -687,12 +595,11 @@ pixman_coalesce (region_type_t * region, /* Region to coalesce */ /* Quicky macro to avoid trivial reject procedure calls to pixman_coalesce */ #define COALESCE(new_reg, prev_band, cur_band) \ - do \ - { \ - if (cur_band - prev_band == new_reg->data->numRects - cur_band) \ - prev_band = pixman_coalesce (new_reg, prev_band, cur_band); \ - else \ - prev_band = cur_band; \ + do { \ + if (cur_band - prev_band == new_reg->data->numRects - cur_band) \ + prev_band = pixman_coalesce(new_reg, prev_band, cur_band); \ + else \ + prev_band = cur_band; \ } while (0) /*- @@ -711,65 +618,59 @@ pixman_coalesce (region_type_t * region, /* Region to coalesce */ * *----------------------------------------------------------------------- */ -static inline pixman_bool_t -pixman_region_append_non_o (region_type_t * region, - box_type_t * r, - box_type_t * r_end, - int y1, - int y2) +static inline pixman_bool_t pixman_region_append_non_o(region_type_t *region, + box_type_t * r, + box_type_t * r_end, + int y1, int y2) { box_type_t *next_rect; - int new_rects; + int new_rects; new_rects = r_end - r; - critical_if_fail (y1 < y2); - critical_if_fail (new_rects != 0); + critical_if_fail(y1 < y2); + critical_if_fail(new_rects != 0); /* Make sure we have enough space for all rectangles to be added */ - RECTALLOC (region, new_rects); - next_rect = PIXREGION_TOP (region); + RECTALLOC(region, new_rects); + next_rect = PIXREGION_TOP(region); region->data->numRects += new_rects; - do - { - critical_if_fail (r->x1 < r->x2); - ADDRECT (next_rect, r->x1, y1, r->x2, y2); - r++; - } - while (r != r_end); + do { + critical_if_fail(r->x1 < r->x2); + ADDRECT(next_rect, r->x1, y1, r->x2, y2); + r++; + } while (r != r_end); return TRUE; } -#define FIND_BAND(r, r_band_end, r_end, ry1) \ - do \ - { \ - ry1 = r->y1; \ - r_band_end = r + 1; \ - while ((r_band_end != r_end) && (r_band_end->y1 == ry1)) { \ - r_band_end++; \ - } \ +#define FIND_BAND(r, r_band_end, r_end, ry1) \ + do { \ + ry1 = r->y1; \ + r_band_end = r + 1; \ + while ((r_band_end != r_end) && (r_band_end->y1 == ry1)) { \ + r_band_end++; \ + } \ } while (0) -#define APPEND_REGIONS(new_reg, r, r_end) \ - do \ - { \ - int new_rects; \ - if ((new_rects = r_end - r)) { \ - RECTALLOC_BAIL (new_reg, new_rects, bail); \ - memmove ((char *)PIXREGION_TOP (new_reg), (char *)r, \ - new_rects * sizeof(box_type_t)); \ - new_reg->data->numRects += new_rects; \ - } \ +#define APPEND_REGIONS(new_reg, r, r_end) \ + do { \ + int new_rects; \ + if ((new_rects = r_end - r)) { \ + RECTALLOC_BAIL(new_reg, new_rects, bail); \ + memmove((char *)PIXREGION_TOP(new_reg), (char *)r, \ + new_rects * sizeof(box_type_t)); \ + new_reg->data->numRects += new_rects; \ + } \ } while (0) /*- *----------------------------------------------------------------------- * pixman_op -- - * Apply an operation to two regions. Called by pixman_region_union, pixman_region_inverse, - * pixman_region_subtract, pixman_region_intersect.... Both regions MUST have at least one - * rectangle, and cannot be the same object. + * Apply an operation to two regions. Called by pixman_region_union, + *pixman_region_inverse, pixman_region_subtract, pixman_region_intersect.... + *Both regions MUST have at least one rectangle, and cannot be the same object. * * Results: * TRUE if successful. @@ -793,53 +694,49 @@ pixman_region_append_non_o (region_type_t * region, *----------------------------------------------------------------------- */ -typedef pixman_bool_t (*overlap_proc_ptr) (region_type_t *region, - box_type_t * r1, - box_type_t * r1_end, - box_type_t * r2, - box_type_t * r2_end, - int y1, - int y2); - -static pixman_bool_t -pixman_op (region_type_t * new_reg, /* Place to store result */ - region_type_t * reg1, /* First region in operation */ - region_type_t * reg2, /* 2d region in operation */ - overlap_proc_ptr overlap_func, /* Function to call for over- - * lapping bands */ - int append_non1, /* Append non-overlapping bands - * in region 1 ? - */ - int append_non2 /* Append non-overlapping bands - * in region 2 ? - */ - ) -{ - box_type_t *r1; /* Pointer into first region */ - box_type_t *r2; /* Pointer into 2d region */ - box_type_t *r1_end; /* End of 1st region */ - box_type_t *r2_end; /* End of 2d region */ - int ybot; /* Bottom of intersection */ - int ytop; /* Top of intersection */ - region_data_type_t *old_data; /* Old data for new_reg */ - int prev_band; /* Index of start of - * previous band in new_reg */ - int cur_band; /* Index of start of current - * band in new_reg */ - box_type_t * r1_band_end; /* End of current band in r1 */ - box_type_t * r2_band_end; /* End of current band in r2 */ - int top; /* Top of non-overlapping band */ - int bot; /* Bottom of non-overlapping band*/ - int r1y1; /* Temps for r1->y1 and r2->y1 */ - int r2y1; - int new_size; - int numRects; +typedef pixman_bool_t (*overlap_proc_ptr)(region_type_t *region, box_type_t *r1, + box_type_t *r1_end, box_type_t *r2, + box_type_t *r2_end, int y1, int y2); + +static pixman_bool_t pixman_op( + region_type_t * new_reg, /* Place to store result */ + region_type_t * reg1, /* First region in operation */ + region_type_t * reg2, /* 2d region in operation */ + overlap_proc_ptr overlap_func, /* Function to call for over- + * lapping bands */ + int append_non1, /* Append non-overlapping bands + * in region 1 ? + */ + int append_non2 /* Append non-overlapping bands + * in region 2 ? + */ +) +{ + box_type_t * r1; /* Pointer into first region */ + box_type_t * r2; /* Pointer into 2d region */ + box_type_t * r1_end; /* End of 1st region */ + box_type_t * r2_end; /* End of 2d region */ + int ybot; /* Bottom of intersection */ + int ytop; /* Top of intersection */ + region_data_type_t *old_data; /* Old data for new_reg */ + int prev_band; /* Index of start of + * previous band in new_reg */ + int cur_band; /* Index of start of current + * band in new_reg */ + box_type_t *r1_band_end; /* End of current band in r1 */ + box_type_t *r2_band_end; /* End of current band in r2 */ + int top; /* Top of non-overlapping band */ + int bot; /* Bottom of non-overlapping band*/ + int r1y1; /* Temps for r1->y1 and r2->y1 */ + int r2y1; + int new_size; + int numRects; /* * Break any region computed from a broken region */ - if (PIXREGION_NAR (reg1) || PIXREGION_NAR (reg2)) - return pixman_break (new_reg); + if (PIXREGION_NAR(reg1) || PIXREGION_NAR(reg2)) + return pixman_break(new_reg); /* * Initialization: @@ -849,44 +746,40 @@ pixman_op (region_type_t * new_reg, /* Place to store result * another array of rectangles for it to use. */ - r1 = PIXREGION_RECTS (reg1); - new_size = PIXREGION_NUMRECTS (reg1); + r1 = PIXREGION_RECTS(reg1); + new_size = PIXREGION_NUMRECTS(reg1); r1_end = r1 + new_size; - numRects = PIXREGION_NUMRECTS (reg2); - r2 = PIXREGION_RECTS (reg2); + numRects = PIXREGION_NUMRECTS(reg2); + r2 = PIXREGION_RECTS(reg2); r2_end = r2 + numRects; - critical_if_fail (r1 != r1_end); - critical_if_fail (r2 != r2_end); + critical_if_fail(r1 != r1_end); + critical_if_fail(r2 != r2_end); old_data = (region_data_type_t *)NULL; if (((new_reg == reg1) && (new_size > 1)) || - ((new_reg == reg2) && (numRects > 1))) - { + ((new_reg == reg2) && (numRects > 1))) { old_data = new_reg->data; new_reg->data = pixman_region_empty_data; } /* guess at new size */ - if (numRects > new_size) - new_size = numRects; + if (numRects > new_size) new_size = numRects; new_size <<= 1; if (!new_reg->data) - new_reg->data = pixman_region_empty_data; + new_reg->data = pixman_region_empty_data; else if (new_reg->data->size) - new_reg->data->numRects = 0; + new_reg->data->numRects = 0; - if (new_size > new_reg->data->size) - { - if (!pixman_rect_alloc (new_reg, new_size)) - { - free (old_data); + if (new_size > new_reg->data->size) { + if (!pixman_rect_alloc(new_reg, new_size)) { + free(old_data); return FALSE; - } + } } /* @@ -903,7 +796,7 @@ pixman_op (region_type_t * new_reg, /* Place to store result * the top of the rectangles of both regions and ybot clips the bottoms. */ - ybot = MIN (r1->y1, r2->y1); + ybot = MIN(r1->y1, r2->y1); /* * prev_band serves to mark the start of the previous band so rectangles @@ -916,101 +809,86 @@ pixman_op (region_type_t * new_reg, /* Place to store result */ prev_band = 0; - do - { + do { /* - * This algorithm proceeds one source-band (as opposed to a - * destination band, which is determined by where the two regions - * intersect) at a time. r1_band_end and r2_band_end serve to mark the - * rectangle after the last one in the current band for their - * respective regions. - */ - critical_if_fail (r1 != r1_end); - critical_if_fail (r2 != r2_end); + * This algorithm proceeds one source-band (as opposed to a + * destination band, which is determined by where the two regions + * intersect) at a time. r1_band_end and r2_band_end serve to mark the + * rectangle after the last one in the current band for their + * respective regions. + */ + critical_if_fail(r1 != r1_end); + critical_if_fail(r2 != r2_end); - FIND_BAND (r1, r1_band_end, r1_end, r1y1); - FIND_BAND (r2, r2_band_end, r2_end, r2y1); + FIND_BAND(r1, r1_band_end, r1_end, r1y1); + FIND_BAND(r2, r2_band_end, r2_end, r2y1); /* - * First handle the band that doesn't intersect, if any. - * - * Note that attention is restricted to one band in the - * non-intersecting region at once, so if a region has n - * bands between the current position and the next place it overlaps - * the other, this entire loop will be passed through n times. - */ - if (r1y1 < r2y1) - { - if (append_non1) - { - top = MAX (r1y1, ybot); - bot = MIN (r1->y2, r2y1); - if (top != bot) - { + * First handle the band that doesn't intersect, if any. + * + * Note that attention is restricted to one band in the + * non-intersecting region at once, so if a region has n + * bands between the current position and the next place it overlaps + * the other, this entire loop will be passed through n times. + */ + if (r1y1 < r2y1) { + if (append_non1) { + top = MAX(r1y1, ybot); + bot = MIN(r1->y2, r2y1); + if (top != bot) { cur_band = new_reg->data->numRects; - if (!pixman_region_append_non_o (new_reg, r1, r1_band_end, top, bot)) - goto bail; - COALESCE (new_reg, prev_band, cur_band); - } - } + if (!pixman_region_append_non_o(new_reg, r1, r1_band_end, + top, bot)) + goto bail; + COALESCE(new_reg, prev_band, cur_band); + } + } ytop = r2y1; - } - else if (r2y1 < r1y1) - { - if (append_non2) - { - top = MAX (r2y1, ybot); - bot = MIN (r2->y2, r1y1); - - if (top != bot) - { + } else if (r2y1 < r1y1) { + if (append_non2) { + top = MAX(r2y1, ybot); + bot = MIN(r2->y2, r1y1); + + if (top != bot) { cur_band = new_reg->data->numRects; - if (!pixman_region_append_non_o (new_reg, r2, r2_band_end, top, bot)) - goto bail; + if (!pixman_region_append_non_o(new_reg, r2, r2_band_end, + top, bot)) + goto bail; - COALESCE (new_reg, prev_band, cur_band); - } - } + COALESCE(new_reg, prev_band, cur_band); + } + } ytop = r1y1; - } - else - { + } else { ytop = r1y1; - } + } /* - * Now see if we've hit an intersecting band. The two bands only - * intersect if ybot > ytop - */ - ybot = MIN (r1->y2, r2->y2); - if (ybot > ytop) - { + * Now see if we've hit an intersecting band. The two bands only + * intersect if ybot > ytop + */ + ybot = MIN(r1->y2, r2->y2); + if (ybot > ytop) { cur_band = new_reg->data->numRects; - if (!(*overlap_func)(new_reg, - r1, r1_band_end, - r2, r2_band_end, - ytop, ybot)) - { - goto bail; - } + if (!(*overlap_func)(new_reg, r1, r1_band_end, r2, r2_band_end, + ytop, ybot)) { + goto bail; + } - COALESCE (new_reg, prev_band, cur_band); - } + COALESCE(new_reg, prev_band, cur_band); + } /* - * If we've finished with a band (y2 == ybot) we skip forward - * in the region to the next band. - */ - if (r1->y2 == ybot) - r1 = r1_band_end; + * If we've finished with a band (y2 == ybot) we skip forward + * in the region to the next band. + */ + if (r1->y2 == ybot) r1 = r1_band_end; - if (r2->y2 == ybot) - r2 = r2_band_end; + if (r2->y2 == ybot) r2 = r2_band_end; - } - while (r1 != r1_end && r2 != r2_end); + } while (r1 != r1_end && r2 != r2_end); /* * Deal with whichever region (if any) still has rectangles left. @@ -1020,69 +898,57 @@ pixman_op (region_type_t * new_reg, /* Place to store result * regardless of how many bands, into one final append to the list. */ - if ((r1 != r1_end) && append_non1) - { + if ((r1 != r1_end) && append_non1) { /* Do first non_overlap1Func call, which may be able to coalesce */ - FIND_BAND (r1, r1_band_end, r1_end, r1y1); + FIND_BAND(r1, r1_band_end, r1_end, r1y1); cur_band = new_reg->data->numRects; - if (!pixman_region_append_non_o (new_reg, - r1, r1_band_end, - MAX (r1y1, ybot), r1->y2)) - { - goto bail; - } + if (!pixman_region_append_non_o(new_reg, r1, r1_band_end, + MAX(r1y1, ybot), r1->y2)) { + goto bail; + } - COALESCE (new_reg, prev_band, cur_band); + COALESCE(new_reg, prev_band, cur_band); /* Just append the rest of the boxes */ - APPEND_REGIONS (new_reg, r1_band_end, r1_end); - } - else if ((r2 != r2_end) && append_non2) - { + APPEND_REGIONS(new_reg, r1_band_end, r1_end); + } else if ((r2 != r2_end) && append_non2) { /* Do first non_overlap2Func call, which may be able to coalesce */ - FIND_BAND (r2, r2_band_end, r2_end, r2y1); + FIND_BAND(r2, r2_band_end, r2_end, r2y1); - cur_band = new_reg->data->numRects; + cur_band = new_reg->data->numRects; - if (!pixman_region_append_non_o (new_reg, - r2, r2_band_end, - MAX (r2y1, ybot), r2->y2)) - { - goto bail; - } + if (!pixman_region_append_non_o(new_reg, r2, r2_band_end, + MAX(r2y1, ybot), r2->y2)) { + goto bail; + } - COALESCE (new_reg, prev_band, cur_band); + COALESCE(new_reg, prev_band, cur_band); /* Append rest of boxes */ - APPEND_REGIONS (new_reg, r2_band_end, r2_end); + APPEND_REGIONS(new_reg, r2_band_end, r2_end); } - free (old_data); + free(old_data); - if (!(numRects = new_reg->data->numRects)) - { - FREE_DATA (new_reg); + if (!(numRects = new_reg->data->numRects)) { + FREE_DATA(new_reg); new_reg->data = pixman_region_empty_data; - } - else if (numRects == 1) - { - new_reg->extents = *PIXREGION_BOXPTR (new_reg); - FREE_DATA (new_reg); + } else if (numRects == 1) { + new_reg->extents = *PIXREGION_BOXPTR(new_reg); + FREE_DATA(new_reg); new_reg->data = (region_data_type_t *)NULL; - } - else - { - DOWNSIZE (new_reg, numRects); + } else { + DOWNSIZE(new_reg, numRects); } return TRUE; bail: - free (old_data); + free(old_data); - return pixman_break (new_reg); + return pixman_break(new_reg); } /*- @@ -1100,23 +966,20 @@ bail: * *----------------------------------------------------------------------- */ -static void -pixman_set_extents (region_type_t *region) +static void pixman_set_extents(region_type_t *region) { box_type_t *box, *box_end; - if (!region->data) - return; + if (!region->data) return; - if (!region->data->size) - { + if (!region->data->size) { region->extents.x2 = region->extents.x1; region->extents.y2 = region->extents.y1; return; } - box = PIXREGION_BOXPTR (region); - box_end = PIXREGION_END (region); + box = PIXREGION_BOXPTR(region); + box_end = PIXREGION_END(region); /* * Since box is the first rectangle in the region, it must have the @@ -1130,18 +993,15 @@ pixman_set_extents (region_type_t *region) region->extents.x2 = box_end->x2; region->extents.y2 = box_end->y2; - critical_if_fail (region->extents.y1 < region->extents.y2); + critical_if_fail(region->extents.y1 < region->extents.y2); - while (box <= box_end) - { - if (box->x1 < region->extents.x1) - region->extents.x1 = box->x1; - if (box->x2 > region->extents.x2) - region->extents.x2 = box->x2; + while (box <= box_end) { + if (box->x1 < region->extents.x1) region->extents.x1 = box->x1; + if (box->x2 > region->extents.x2) region->extents.x2 = box->x2; box++; } - critical_if_fail (region->extents.x1 < region->extents.x2); + critical_if_fail(region->extents.x1 < region->extents.x2); } /*====================================================================== @@ -1161,137 +1021,108 @@ pixman_set_extents (region_type_t *region) *----------------------------------------------------------------------- */ /*ARGSUSED*/ -static pixman_bool_t -pixman_region_intersect_o (region_type_t *region, - box_type_t * r1, - box_type_t * r1_end, - box_type_t * r2, - box_type_t * r2_end, - int y1, - int y2) +static pixman_bool_t pixman_region_intersect_o( + region_type_t *region, box_type_t *r1, box_type_t *r1_end, box_type_t *r2, + box_type_t *r2_end, int y1, int y2) { - int x1; - int x2; - box_type_t * next_rect; + int x1; + int x2; + box_type_t *next_rect; - next_rect = PIXREGION_TOP (region); + next_rect = PIXREGION_TOP(region); - critical_if_fail (y1 < y2); - critical_if_fail (r1 != r1_end && r2 != r2_end); + critical_if_fail(y1 < y2); + critical_if_fail(r1 != r1_end && r2 != r2_end); - do - { - x1 = MAX (r1->x1, r2->x1); - x2 = MIN (r1->x2, r2->x2); + do { + x1 = MAX(r1->x1, r2->x1); + x2 = MIN(r1->x2, r2->x2); /* - * If there's any overlap between the two rectangles, add that - * overlap to the new region. - */ - if (x1 < x2) - NEWRECT (region, next_rect, x1, y1, x2, y2); + * If there's any overlap between the two rectangles, add that + * overlap to the new region. + */ + if (x1 < x2) NEWRECT(region, next_rect, x1, y1, x2, y2); /* - * Advance the pointer(s) with the leftmost right side, since the next - * rectangle on that list may still overlap the other region's - * current rectangle. - */ - if (r1->x2 == x2) - { + * Advance the pointer(s) with the leftmost right side, since the next + * rectangle on that list may still overlap the other region's + * current rectangle. + */ + if (r1->x2 == x2) { r1++; - } - if (r2->x2 == x2) - { + } + if (r2->x2 == x2) { r2++; - } - } - while ((r1 != r1_end) && (r2 != r2_end)); + } + } while ((r1 != r1_end) && (r2 != r2_end)); return TRUE; } -PIXMAN_EXPORT pixman_bool_t -PREFIX (_intersect) (region_type_t * new_reg, - region_type_t * reg1, - region_type_t * reg2) +PIXMAN_EXPORT pixman_bool_t PREFIX(_intersect)(region_type_t *new_reg, + region_type_t *reg1, + region_type_t *reg2) { - GOOD (reg1); - GOOD (reg2); - GOOD (new_reg); + GOOD(reg1); + GOOD(reg2); + GOOD(new_reg); /* check for trivial reject */ - if (PIXREGION_NIL (reg1) || PIXREGION_NIL (reg2) || - !EXTENTCHECK (®1->extents, ®2->extents)) - { + if (PIXREGION_NIL(reg1) || PIXREGION_NIL(reg2) || + !EXTENTCHECK(®1->extents, ®2->extents)) { /* Covers about 20% of all cases */ - FREE_DATA (new_reg); + FREE_DATA(new_reg); new_reg->extents.x2 = new_reg->extents.x1; new_reg->extents.y2 = new_reg->extents.y1; - if (PIXREGION_NAR (reg1) || PIXREGION_NAR (reg2)) - { + if (PIXREGION_NAR(reg1) || PIXREGION_NAR(reg2)) { new_reg->data = pixman_broken_data; return FALSE; - } - else - { - new_reg->data = pixman_region_empty_data; - } - } - else if (!reg1->data && !reg2->data) - { + } else { + new_reg->data = pixman_region_empty_data; + } + } else if (!reg1->data && !reg2->data) { /* Covers about 80% of cases that aren't trivially rejected */ - new_reg->extents.x1 = MAX (reg1->extents.x1, reg2->extents.x1); - new_reg->extents.y1 = MAX (reg1->extents.y1, reg2->extents.y1); - new_reg->extents.x2 = MIN (reg1->extents.x2, reg2->extents.x2); - new_reg->extents.y2 = MIN (reg1->extents.y2, reg2->extents.y2); + new_reg->extents.x1 = MAX(reg1->extents.x1, reg2->extents.x1); + new_reg->extents.y1 = MAX(reg1->extents.y1, reg2->extents.y1); + new_reg->extents.x2 = MIN(reg1->extents.x2, reg2->extents.x2); + new_reg->extents.y2 = MIN(reg1->extents.y2, reg2->extents.y2); - FREE_DATA (new_reg); + FREE_DATA(new_reg); - new_reg->data = (region_data_type_t *)NULL; - } - else if (!reg2->data && SUBSUMES (®2->extents, ®1->extents)) - { - return PREFIX (_copy) (new_reg, reg1); - } - else if (!reg1->data && SUBSUMES (®1->extents, ®2->extents)) - { - return PREFIX (_copy) (new_reg, reg2); - } - else if (reg1 == reg2) - { - return PREFIX (_copy) (new_reg, reg1); - } - else - { + new_reg->data = (region_data_type_t *)NULL; + } else if (!reg2->data && SUBSUMES(®2->extents, ®1->extents)) { + return PREFIX(_copy)(new_reg, reg1); + } else if (!reg1->data && SUBSUMES(®1->extents, ®2->extents)) { + return PREFIX(_copy)(new_reg, reg2); + } else if (reg1 == reg2) { + return PREFIX(_copy)(new_reg, reg1); + } else { /* General purpose intersection */ - if (!pixman_op (new_reg, reg1, reg2, pixman_region_intersect_o, FALSE, FALSE)) - return FALSE; + if (!pixman_op(new_reg, reg1, reg2, pixman_region_intersect_o, FALSE, + FALSE)) + return FALSE; - pixman_set_extents (new_reg); + pixman_set_extents(new_reg); } - GOOD (new_reg); - return(TRUE); -} - -#define MERGERECT(r) \ - do \ - { \ - if (r->x1 <= x2) \ - { \ - /* Merge with current rectangle */ \ - if (x2 < r->x2) \ - x2 = r->x2; \ - } \ - else \ - { \ - /* Add current rectangle, start new one */ \ - NEWRECT (region, next_rect, x1, y1, x2, y2); \ - x1 = r->x1; \ - x2 = r->x2; \ - } \ - r++; \ + GOOD(new_reg); + return (TRUE); +} + +#define MERGERECT(r) \ + do { \ + if (r->x1 <= x2) { \ + /* Merge with current rectangle */ \ + if (x2 < r->x2) x2 = r->x2; \ + } else { \ + /* Add current rectangle, start new one */ \ + NEWRECT(region, next_rect, x1, y1, x2, y2); \ + x1 = r->x1; \ + x2 = r->x2; \ + } \ + r++; \ } while (0) /*====================================================================== @@ -1313,75 +1144,59 @@ PREFIX (_intersect) (region_type_t * new_reg, * *----------------------------------------------------------------------- */ -static pixman_bool_t -pixman_region_union_o (region_type_t *region, - box_type_t * r1, - box_type_t * r1_end, - box_type_t * r2, - box_type_t * r2_end, - int y1, - int y2) +static pixman_bool_t pixman_region_union_o(region_type_t *region, + box_type_t *r1, box_type_t *r1_end, + box_type_t *r2, box_type_t *r2_end, + int y1, int y2) { box_type_t *next_rect; - int x1; /* left and right side of current union */ - int x2; + int x1; /* left and right side of current union */ + int x2; - critical_if_fail (y1 < y2); - critical_if_fail (r1 != r1_end && r2 != r2_end); + critical_if_fail(y1 < y2); + critical_if_fail(r1 != r1_end && r2 != r2_end); - next_rect = PIXREGION_TOP (region); + next_rect = PIXREGION_TOP(region); /* Start off current rectangle */ - if (r1->x1 < r2->x1) - { + if (r1->x1 < r2->x1) { x1 = r1->x1; x2 = r1->x2; r1++; - } - else - { + } else { x1 = r2->x1; x2 = r2->x2; r2++; } - while (r1 != r1_end && r2 != r2_end) - { + while (r1 != r1_end && r2 != r2_end) { if (r1->x1 < r2->x1) - MERGERECT (r1); - else - MERGERECT (r2); + MERGERECT(r1); + else + MERGERECT(r2); } /* Finish off whoever (if any) is left */ - if (r1 != r1_end) - { - do - { - MERGERECT (r1); - } - while (r1 != r1_end); - } - else if (r2 != r2_end) - { - do - { - MERGERECT (r2); - } - while (r2 != r2_end); + if (r1 != r1_end) { + do { + MERGERECT(r1); + } while (r1 != r1_end); + } else if (r2 != r2_end) { + do { + MERGERECT(r2); + } while (r2 != r2_end); } /* Add current rectangle */ - NEWRECT (region, next_rect, x1, y1, x2, y2); + NEWRECT(region, next_rect, x1, y1, x2, y2); return TRUE; } -PIXMAN_EXPORT pixman_bool_t -PREFIX(_intersect_rect) (region_type_t *dest, - region_type_t *source, - int x, int y, - unsigned int width, - unsigned int height) +PIXMAN_EXPORT pixman_bool_t PREFIX(_intersect_rect)(region_type_t *dest, + region_type_t *source, + int x, int y, + unsigned int width, + unsigned int height) { region_type_t region; @@ -1391,24 +1206,20 @@ PREFIX(_intersect_rect) (region_type_t *dest, region.extents.x2 = x + width; region.extents.y2 = y + height; - return PREFIX(_intersect) (dest, source, ®ion); + return PREFIX(_intersect)(dest, source, ®ion); } -PIXMAN_EXPORT pixman_bool_t -PREFIX (_union) (region_type_t *new_reg, - region_type_t *reg1, - region_type_t *reg2); +PIXMAN_EXPORT pixman_bool_t PREFIX(_union)(region_type_t *new_reg, + region_type_t *reg1, + region_type_t *reg2); /* Convenience function for performing union of region with a * single rectangle */ -PIXMAN_EXPORT pixman_bool_t -PREFIX (_union_rect) (region_type_t *dest, - region_type_t *source, - int x, - int y, - unsigned int width, - unsigned int height) +PIXMAN_EXPORT pixman_bool_t PREFIX(_union_rect)(region_type_t *dest, + region_type_t *source, int x, + int y, unsigned int width, + unsigned int height) { region_type_t region; @@ -1417,97 +1228,84 @@ PREFIX (_union_rect) (region_type_t *dest, region.extents.x2 = x + width; region.extents.y2 = y + height; - if (!GOOD_RECT (®ion.extents)) - { - if (BAD_RECT (®ion.extents)) - _pixman_log_error (FUNC, "Invalid rectangle passed"); - return PREFIX (_copy) (dest, source); + if (!GOOD_RECT(®ion.extents)) { + if (BAD_RECT(®ion.extents)) + _pixman_log_error(FUNC, "Invalid rectangle passed"); + return PREFIX(_copy)(dest, source); } region.data = NULL; - return PREFIX (_union) (dest, source, ®ion); + return PREFIX(_union)(dest, source, ®ion); } -PIXMAN_EXPORT pixman_bool_t -PREFIX (_union) (region_type_t *new_reg, - region_type_t *reg1, - region_type_t *reg2) +PIXMAN_EXPORT pixman_bool_t PREFIX(_union)(region_type_t *new_reg, + region_type_t *reg1, + region_type_t *reg2) { /* Return TRUE if some overlap * between reg1, reg2 */ - GOOD (reg1); - GOOD (reg2); - GOOD (new_reg); + GOOD(reg1); + GOOD(reg2); + GOOD(new_reg); /* checks all the simple cases */ /* * Region 1 and 2 are the same */ - if (reg1 == reg2) - return PREFIX (_copy) (new_reg, reg1); + if (reg1 == reg2) return PREFIX(_copy)(new_reg, reg1); /* * Region 1 is empty */ - if (PIXREGION_NIL (reg1)) - { - if (PIXREGION_NAR (reg1)) - return pixman_break (new_reg); + if (PIXREGION_NIL(reg1)) { + if (PIXREGION_NAR(reg1)) return pixman_break(new_reg); - if (new_reg != reg2) - return PREFIX (_copy) (new_reg, reg2); + if (new_reg != reg2) return PREFIX(_copy)(new_reg, reg2); - return TRUE; + return TRUE; } /* * Region 2 is empty */ - if (PIXREGION_NIL (reg2)) - { - if (PIXREGION_NAR (reg2)) - return pixman_break (new_reg); + if (PIXREGION_NIL(reg2)) { + if (PIXREGION_NAR(reg2)) return pixman_break(new_reg); - if (new_reg != reg1) - return PREFIX (_copy) (new_reg, reg1); + if (new_reg != reg1) return PREFIX(_copy)(new_reg, reg1); - return TRUE; + return TRUE; } /* * Region 1 completely subsumes region 2 */ - if (!reg1->data && SUBSUMES (®1->extents, ®2->extents)) - { - if (new_reg != reg1) - return PREFIX (_copy) (new_reg, reg1); + if (!reg1->data && SUBSUMES(®1->extents, ®2->extents)) { + if (new_reg != reg1) return PREFIX(_copy)(new_reg, reg1); - return TRUE; + return TRUE; } /* * Region 2 completely subsumes region 1 */ - if (!reg2->data && SUBSUMES (®2->extents, ®1->extents)) - { - if (new_reg != reg2) - return PREFIX (_copy) (new_reg, reg2); + if (!reg2->data && SUBSUMES(®2->extents, ®1->extents)) { + if (new_reg != reg2) return PREFIX(_copy)(new_reg, reg2); - return TRUE; + return TRUE; } - if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE)) - return FALSE; + if (!pixman_op(new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE)) + return FALSE; - new_reg->extents.x1 = MIN (reg1->extents.x1, reg2->extents.x1); - new_reg->extents.y1 = MIN (reg1->extents.y1, reg2->extents.y1); - new_reg->extents.x2 = MAX (reg1->extents.x2, reg2->extents.x2); - new_reg->extents.y2 = MAX (reg1->extents.y2, reg2->extents.y2); + new_reg->extents.x1 = MIN(reg1->extents.x1, reg2->extents.x1); + new_reg->extents.y1 = MIN(reg1->extents.y1, reg2->extents.y1); + new_reg->extents.x2 = MAX(reg1->extents.x2, reg2->extents.x2); + new_reg->extents.y2 = MAX(reg1->extents.y2, reg2->extents.y2); - GOOD (new_reg); + GOOD(new_reg); return TRUE; } @@ -1531,114 +1329,88 @@ PREFIX (_union) (region_type_t *new_reg, *----------------------------------------------------------------------- */ /*ARGSUSED*/ -static pixman_bool_t -pixman_region_subtract_o (region_type_t * region, - box_type_t * r1, - box_type_t * r1_end, - box_type_t * r2, - box_type_t * r2_end, - int y1, - int y2) -{ - box_type_t * next_rect; - int x1; +static pixman_bool_t pixman_region_subtract_o( + region_type_t *region, box_type_t *r1, box_type_t *r1_end, box_type_t *r2, + box_type_t *r2_end, int y1, int y2) +{ + box_type_t *next_rect; + int x1; x1 = r1->x1; - critical_if_fail (y1 < y2); - critical_if_fail (r1 != r1_end && r2 != r2_end); + critical_if_fail(y1 < y2); + critical_if_fail(r1 != r1_end && r2 != r2_end); - next_rect = PIXREGION_TOP (region); + next_rect = PIXREGION_TOP(region); - do - { - if (r2->x2 <= x1) - { + do { + if (r2->x2 <= x1) { /* - * Subtrahend entirely to left of minuend: go to next subtrahend. - */ + * Subtrahend entirely to left of minuend: go to next subtrahend. + */ r2++; - } - else if (r2->x1 <= x1) - { + } else if (r2->x1 <= x1) { /* - * Subtrahend precedes minuend: nuke left edge of minuend. - */ + * Subtrahend precedes minuend: nuke left edge of minuend. + */ x1 = r2->x2; - if (x1 >= r1->x2) - { + if (x1 >= r1->x2) { /* - * Minuend completely covered: advance to next minuend and - * reset left fence to edge of new minuend. - */ + * Minuend completely covered: advance to next minuend and + * reset left fence to edge of new minuend. + */ r1++; - if (r1 != r1_end) - x1 = r1->x1; - } - else - { + if (r1 != r1_end) x1 = r1->x1; + } else { /* - * Subtrahend now used up since it doesn't extend beyond - * minuend - */ + * Subtrahend now used up since it doesn't extend beyond + * minuend + */ r2++; - } - } - else if (r2->x1 < r1->x2) - { + } + } else if (r2->x1 < r1->x2) { /* - * Left part of subtrahend covers part of minuend: add uncovered - * part of minuend to region and skip to next subtrahend. - */ - critical_if_fail (x1 < r2->x1); - NEWRECT (region, next_rect, x1, y1, r2->x1, y2); + * Left part of subtrahend covers part of minuend: add uncovered + * part of minuend to region and skip to next subtrahend. + */ + critical_if_fail(x1 < r2->x1); + NEWRECT(region, next_rect, x1, y1, r2->x1, y2); x1 = r2->x2; - if (x1 >= r1->x2) - { + if (x1 >= r1->x2) { /* - * Minuend used up: advance to new... - */ + * Minuend used up: advance to new... + */ r1++; - if (r1 != r1_end) - x1 = r1->x1; - } - else - { + if (r1 != r1_end) x1 = r1->x1; + } else { /* - * Subtrahend used up - */ + * Subtrahend used up + */ r2++; - } - } - else - { + } + } else { /* - * Minuend used up: add any remaining piece before advancing. - */ - if (r1->x2 > x1) - NEWRECT (region, next_rect, x1, y1, r1->x2, y2); + * Minuend used up: add any remaining piece before advancing. + */ + if (r1->x2 > x1) NEWRECT(region, next_rect, x1, y1, r1->x2, y2); r1++; - if (r1 != r1_end) - x1 = r1->x1; - } - } - while ((r1 != r1_end) && (r2 != r2_end)); + if (r1 != r1_end) x1 = r1->x1; + } + } while ((r1 != r1_end) && (r2 != r2_end)); /* * Add remaining minuend rectangles to region. */ - while (r1 != r1_end) - { - critical_if_fail (x1 < r1->x2); + while (r1 != r1_end) { + critical_if_fail(x1 < r1->x2); - NEWRECT (region, next_rect, x1, y1, r1->x2, y2); + NEWRECT(region, next_rect, x1, y1, r1->x2, y2); r1++; - if (r1 != r1_end) - x1 = r1->x1; + if (r1 != r1_end) x1 = r1->x1; } return TRUE; } @@ -1657,27 +1429,22 @@ pixman_region_subtract_o (region_type_t * region, * *----------------------------------------------------------------------- */ -PIXMAN_EXPORT pixman_bool_t -PREFIX (_subtract) (region_type_t *reg_d, - region_type_t *reg_m, - region_type_t *reg_s) +PIXMAN_EXPORT pixman_bool_t PREFIX(_subtract)(region_type_t *reg_d, + region_type_t *reg_m, + region_type_t *reg_s) { - GOOD (reg_m); - GOOD (reg_s); - GOOD (reg_d); + GOOD(reg_m); + GOOD(reg_s); + GOOD(reg_d); /* check for trivial rejects */ - if (PIXREGION_NIL (reg_m) || PIXREGION_NIL (reg_s) || - !EXTENTCHECK (®_m->extents, ®_s->extents)) - { - if (PIXREGION_NAR (reg_s)) - return pixman_break (reg_d); + if (PIXREGION_NIL(reg_m) || PIXREGION_NIL(reg_s) || + !EXTENTCHECK(®_m->extents, ®_s->extents)) { + if (PIXREGION_NAR(reg_s)) return pixman_break(reg_d); - return PREFIX (_copy) (reg_d, reg_m); - } - else if (reg_m == reg_s) - { - FREE_DATA (reg_d); + return PREFIX(_copy)(reg_d, reg_m); + } else if (reg_m == reg_s) { + FREE_DATA(reg_d); reg_d->extents.x2 = reg_d->extents.x1; reg_d->extents.y2 = reg_d->extents.y1; reg_d->data = pixman_region_empty_data; @@ -1688,8 +1455,8 @@ PREFIX (_subtract) (region_type_t *reg_d, /* Add those rectangles in region 1 that aren't in region 2, do yucky subtraction for overlaps, and just throw away rectangles in region 2 that aren't in region 1 */ - if (!pixman_op (reg_d, reg_m, reg_s, pixman_region_subtract_o, TRUE, FALSE)) - return FALSE; + if (!pixman_op(reg_d, reg_m, reg_s, pixman_region_subtract_o, TRUE, FALSE)) + return FALSE; /* * Can't alter reg_d's extents before we call pixman_op because @@ -1698,8 +1465,8 @@ PREFIX (_subtract) (region_type_t *reg_d, * way there's no checking against rectangles that will be nuked * due to coalescing, so we have to examine fewer rectangles. */ - pixman_set_extents (reg_d); - GOOD (reg_d); + pixman_set_extents(reg_d); + GOOD(reg_d); return TRUE; } #if 0 @@ -1769,34 +1536,28 @@ PREFIX (_inverse) (region_type_t *new_reg, /* Destination region */ /* In time O(log n), locate the first box whose y2 is greater than y. * Return @end if no such box exists. */ -static box_type_t * -find_box_for_y (box_type_t *begin, box_type_t *end, int y) +static box_type_t *find_box_for_y(box_type_t *begin, box_type_t *end, int y) { box_type_t *mid; - if (end == begin) - return end; + if (end == begin) return end; - if (end - begin == 1) - { - if (begin->y2 > y) - return begin; - else - return end; + if (end - begin == 1) { + if (begin->y2 > y) + return begin; + else + return end; } mid = begin + (end - begin) / 2; - if (mid->y2 > y) - { - /* If no box is found in [begin, mid], the function - * will return @mid, which is then known to be the - * correct answer. - */ - return find_box_for_y (begin, mid, y); - } - else - { - return find_box_for_y (mid, end, y); + if (mid->y2 > y) { + /* If no box is found in [begin, mid], the function + * will return @mid, which is then known to be the + * correct answer. + */ + return find_box_for_y(begin, mid, y); + } else { + return find_box_for_y(mid, end, y); } } @@ -1817,30 +1578,28 @@ find_box_for_y (box_type_t *begin, box_type_t *end, int y) * that doesn't overlap the box at all and part_in is false) */ PIXMAN_EXPORT pixman_region_overlap_t -PREFIX (_contains_rectangle) (region_type_t * region, - box_type_t * prect) + PREFIX(_contains_rectangle)(region_type_t *region, box_type_t *prect) { - box_type_t * pbox; - box_type_t * pbox_end; - int part_in, part_out; - int numRects; - int x, y; + box_type_t *pbox; + box_type_t *pbox_end; + int part_in, part_out; + int numRects; + int x, y; - GOOD (region); + GOOD(region); - numRects = PIXREGION_NUMRECTS (region); + numRects = PIXREGION_NUMRECTS(region); /* useful optimization */ - if (!numRects || !EXTENTCHECK (®ion->extents, prect)) - return(PIXMAN_REGION_OUT); + if (!numRects || !EXTENTCHECK(®ion->extents, prect)) + return (PIXMAN_REGION_OUT); - if (numRects == 1) - { + if (numRects == 1) { /* We know that it must be PIXMAN_REGION_IN or PIXMAN_REGION_PART */ - if (SUBSUMES (®ion->extents, prect)) - return(PIXMAN_REGION_IN); + if (SUBSUMES(®ion->extents, prect)) + return (PIXMAN_REGION_IN); else - return(PIXMAN_REGION_PART); + return (PIXMAN_REGION_PART); } part_out = FALSE; @@ -1850,73 +1609,56 @@ PREFIX (_contains_rectangle) (region_type_t * region, x = prect->x1; y = prect->y1; - /* can stop when both part_out and part_in are TRUE, or we reach prect->y2 */ - for (pbox = PIXREGION_BOXPTR (region), pbox_end = pbox + numRects; - pbox != pbox_end; - pbox++) - { - /* getting up to speed or skipping remainder of band */ - if (pbox->y2 <= y) - { - if ((pbox = find_box_for_y (pbox, pbox_end, y)) == pbox_end) - break; - } + /* can stop when both part_out and part_in are TRUE, or we reach prect->y2 + */ + for (pbox = PIXREGION_BOXPTR(region), pbox_end = pbox + numRects; + pbox != pbox_end; pbox++) { + /* getting up to speed or skipping remainder of band */ + if (pbox->y2 <= y) { + if ((pbox = find_box_for_y(pbox, pbox_end, y)) == pbox_end) break; + } - if (pbox->y1 > y) - { - part_out = TRUE; /* missed part of rectangle above */ - if (part_in || (pbox->y1 >= prect->y2)) - break; - y = pbox->y1; /* x guaranteed to be == prect->x1 */ - } + if (pbox->y1 > y) { + part_out = TRUE; /* missed part of rectangle above */ + if (part_in || (pbox->y1 >= prect->y2)) break; + y = pbox->y1; /* x guaranteed to be == prect->x1 */ + } - if (pbox->x2 <= x) - continue; /* not far enough over yet */ + if (pbox->x2 <= x) continue; /* not far enough over yet */ - if (pbox->x1 > x) - { - part_out = TRUE; /* missed part of rectangle to left */ - if (part_in) - break; - } + if (pbox->x1 > x) { + part_out = TRUE; /* missed part of rectangle to left */ + if (part_in) break; + } - if (pbox->x1 < prect->x2) - { - part_in = TRUE; /* definitely overlap */ - if (part_out) - break; - } + if (pbox->x1 < prect->x2) { + part_in = TRUE; /* definitely overlap */ + if (part_out) break; + } - if (pbox->x2 >= prect->x2) - { - y = pbox->y2; /* finished with this band */ - if (y >= prect->y2) - break; - x = prect->x1; /* reset x out to left again */ - } - else - { + if (pbox->x2 >= prect->x2) { + y = pbox->y2; /* finished with this band */ + if (y >= prect->y2) break; + x = prect->x1; /* reset x out to left again */ + } else { /* - * Because boxes in a band are maximal width, if the first box - * to overlap the rectangle doesn't completely cover it in that - * band, the rectangle must be partially out, since some of it - * will be uncovered in that band. part_in will have been set true - * by now... - */ + * Because boxes in a band are maximal width, if the first box + * to overlap the rectangle doesn't completely cover it in that + * band, the rectangle must be partially out, since some of it + * will be uncovered in that band. part_in will have been set true + * by now... + */ part_out = TRUE; break; - } + } } - if (part_in) - { + if (part_in) { if (y < prect->y2) - return PIXMAN_REGION_PART; + return PIXMAN_REGION_PART; else - return PIXMAN_REGION_IN; - } - else - { + return PIXMAN_REGION_IN; + } else { return PIXMAN_REGION_OUT; } } @@ -1925,116 +1667,104 @@ PREFIX (_contains_rectangle) (region_type_t * region, * translates in place */ -PIXMAN_EXPORT void -PREFIX (_translate) (region_type_t *region, int x, int y) +PIXMAN_EXPORT void PREFIX(_translate)(region_type_t *region, int x, int y) { overflow_int_t x1, x2, y1, y2; - int nbox; - box_type_t * pbox; + int nbox; + box_type_t * pbox; - GOOD (region); + GOOD(region); region->extents.x1 = x1 = region->extents.x1 + x; region->extents.y1 = y1 = region->extents.y1 + y; region->extents.x2 = x2 = region->extents.x2 + x; region->extents.y2 = y2 = region->extents.y2 + y; - if (((x1 - PIXMAN_REGION_MIN) | (y1 - PIXMAN_REGION_MIN) | (PIXMAN_REGION_MAX - x2) | (PIXMAN_REGION_MAX - y2)) >= 0) - { - if (region->data && (nbox = region->data->numRects)) - { - for (pbox = PIXREGION_BOXPTR (region); nbox--; pbox++) - { + if (((x1 - PIXMAN_REGION_MIN) | (y1 - PIXMAN_REGION_MIN) | + (PIXMAN_REGION_MAX - x2) | (PIXMAN_REGION_MAX - y2)) >= 0) { + if (region->data && (nbox = region->data->numRects)) { + for (pbox = PIXREGION_BOXPTR(region); nbox--; pbox++) { pbox->x1 += x; pbox->y1 += y; pbox->x2 += x; pbox->y2 += y; + } } - } return; } - if (((x2 - PIXMAN_REGION_MIN) | (y2 - PIXMAN_REGION_MIN) | (PIXMAN_REGION_MAX - x1) | (PIXMAN_REGION_MAX - y1)) <= 0) - { + if (((x2 - PIXMAN_REGION_MIN) | (y2 - PIXMAN_REGION_MIN) | + (PIXMAN_REGION_MAX - x1) | (PIXMAN_REGION_MAX - y1)) <= 0) { region->extents.x2 = region->extents.x1; region->extents.y2 = region->extents.y1; - FREE_DATA (region); + FREE_DATA(region); region->data = pixman_region_empty_data; return; } if (x1 < PIXMAN_REGION_MIN) - region->extents.x1 = PIXMAN_REGION_MIN; + region->extents.x1 = PIXMAN_REGION_MIN; else if (x2 > PIXMAN_REGION_MAX) - region->extents.x2 = PIXMAN_REGION_MAX; + region->extents.x2 = PIXMAN_REGION_MAX; if (y1 < PIXMAN_REGION_MIN) - region->extents.y1 = PIXMAN_REGION_MIN; + region->extents.y1 = PIXMAN_REGION_MIN; else if (y2 > PIXMAN_REGION_MAX) - region->extents.y2 = PIXMAN_REGION_MAX; + region->extents.y2 = PIXMAN_REGION_MAX; - if (region->data && (nbox = region->data->numRects)) - { - box_type_t * pbox_out; + if (region->data && (nbox = region->data->numRects)) { + box_type_t *pbox_out; - for (pbox_out = pbox = PIXREGION_BOXPTR (region); nbox--; pbox++) - { + for (pbox_out = pbox = PIXREGION_BOXPTR(region); nbox--; pbox++) { pbox_out->x1 = x1 = pbox->x1 + x; pbox_out->y1 = y1 = pbox->y1 + y; pbox_out->x2 = x2 = pbox->x2 + x; pbox_out->y2 = y2 = pbox->y2 + y; if (((x2 - PIXMAN_REGION_MIN) | (y2 - PIXMAN_REGION_MIN) | - (PIXMAN_REGION_MAX - x1) | (PIXMAN_REGION_MAX - y1)) <= 0) - { + (PIXMAN_REGION_MAX - x1) | (PIXMAN_REGION_MAX - y1)) <= 0) { region->data->numRects--; continue; - } + } if (x1 < PIXMAN_REGION_MIN) - pbox_out->x1 = PIXMAN_REGION_MIN; + pbox_out->x1 = PIXMAN_REGION_MIN; else if (x2 > PIXMAN_REGION_MAX) - pbox_out->x2 = PIXMAN_REGION_MAX; + pbox_out->x2 = PIXMAN_REGION_MAX; if (y1 < PIXMAN_REGION_MIN) - pbox_out->y1 = PIXMAN_REGION_MIN; + pbox_out->y1 = PIXMAN_REGION_MIN; else if (y2 > PIXMAN_REGION_MAX) - pbox_out->y2 = PIXMAN_REGION_MAX; + pbox_out->y2 = PIXMAN_REGION_MAX; pbox_out++; - } + } - if (pbox_out != pbox) - { - if (region->data->numRects == 1) - { - region->extents = *PIXREGION_BOXPTR (region); - FREE_DATA (region); + if (pbox_out != pbox) { + if (region->data->numRects == 1) { + region->extents = *PIXREGION_BOXPTR(region); + FREE_DATA(region); region->data = (region_data_type_t *)NULL; + } else { + pixman_set_extents(region); + } } - else - { - pixman_set_extents (region); - } - } } - GOOD (region); + GOOD(region); } -PIXMAN_EXPORT int -PREFIX (_not_empty) (region_type_t * region) +PIXMAN_EXPORT int PREFIX(_not_empty)(region_type_t *region) { - GOOD (region); + GOOD(region); - return(!PIXREGION_NIL (region)); + return (!PIXREGION_NIL(region)); } -PIXMAN_EXPORT box_type_t * -PREFIX (_extents) (region_type_t * region) +PIXMAN_EXPORT box_type_t *PREFIX(_extents)(region_type_t *region) { - GOOD (region); + GOOD(region); - return(®ion->extents); + return (®ion->extents); } typedef region_type_t VRegionPrivate; @@ -2043,11 +1773,11 @@ typedef region_type_t VRegionPrivate; V_BEGIN_NAMESPACE -static VRegionPrivate regionPrivate = {{0,0,0,0}, NULL}; +static VRegionPrivate regionPrivate = {{0, 0, 0, 0}, NULL}; struct VRegionData { - VRegionData():ref(-1),rgn(®ionPrivate){} - RefCount ref; + VRegionData() : ref(-1), rgn(®ionPrivate) {} + RefCount ref; VRegionPrivate *rgn; }; @@ -2069,8 +1799,7 @@ void VRegion::cleanUp(VRegionData *x) void VRegion::detach() { - if (d->ref.isShared()) - *this = copy(); + if (d->ref.isShared()) *this = copy(); } VRegion VRegion::copy() const @@ -2080,16 +1809,12 @@ VRegion VRegion::copy() const r.d = new VRegionData; r.d->rgn = new VRegionPrivate; r.d->ref.setOwned(); - PREFIX (_init) (r.d->rgn); - if (d != &shared_empty) - PREFIX(_copy)(r.d->rgn, d->rgn); + PREFIX(_init)(r.d->rgn); + if (d != &shared_empty) PREFIX(_copy)(r.d->rgn, d->rgn); return r; } -VRegion::VRegion() - : d(const_cast(&shared_empty)) -{ -} +VRegion::VRegion() : d(const_cast(&shared_empty)) {} VRegion::VRegion(int x, int y, int w, int h) { @@ -2101,7 +1826,7 @@ VRegion::VRegion(int x, int y, int w, int h) VRegion::VRegion(const VRect &r) { if (r.isEmpty()) { - d = const_cast(&shared_empty); + d = const_cast(&shared_empty); } else { d = new VRegionData; d->rgn = new VRegionPrivate; @@ -2116,17 +1841,15 @@ VRegion::VRegion(const VRegion &r) d->ref.ref(); } -VRegion::VRegion(VRegion &&other): d(other.d) +VRegion::VRegion(VRegion &&other) : d(other.d) { - other.d = const_cast(&shared_empty); - + other.d = const_cast(&shared_empty); } VRegion &VRegion::operator=(const VRegion &r) { r.d->ref.ref(); - if (!d->ref.deref()) - cleanUp(d); + if (!d->ref.deref()) cleanUp(d); d = r.d; return *this; @@ -2134,17 +1857,15 @@ VRegion &VRegion::operator=(const VRegion &r) inline VRegion &VRegion::operator=(VRegion &&other) { - if (!d->ref.deref()) - cleanUp(d); + if (!d->ref.deref()) cleanUp(d); d = other.d; - other.d = const_cast(&shared_empty); + other.d = const_cast(&shared_empty); return *this; } VRegion::~VRegion() { - if (!d->ref.deref()) - cleanUp(d); + if (!d->ref.deref()) cleanUp(d); } bool VRegion::isEmpty() const @@ -2154,8 +1875,7 @@ bool VRegion::isEmpty() const void VRegion::translate(const VPoint &p) { - if (p == VPoint() || isEmpty()) - return; + if (p == VPoint() || isEmpty()) return; detach(); PREFIX(_translate)(d->rgn, p.x(), p.y()); @@ -2175,24 +1895,22 @@ bool VRegion::within(const VRect &r1) const { box_type_t *r2 = PREFIX(_extents)(d->rgn); - return r2->x1 >= r1.left() && r2->x2 <= r1.right() - && r2->y1 >= r1.top() && r2->y2 <= r1.bottom(); + return r2->x1 >= r1.left() && r2->x2 <= r1.right() && r2->y1 >= r1.top() && + r2->y2 <= r1.bottom(); } bool VRegion::contains(const VRect &r) const { box_type_t box = {r.left(), r.top(), r.right(), r.bottom()}; - pixman_region_overlap_t res = PREFIX (_contains_rectangle)(d->rgn, &box); - if (res == PIXMAN_REGION_IN) - return true; + pixman_region_overlap_t res = PREFIX(_contains_rectangle)(d->rgn, &box); + if (res == PIXMAN_REGION_IN) return true; return false; } VRegion VRegion::united(const VRect &r) const { - if (isEmpty()) - return r; + if (isEmpty()) return r; if (contains(r)) { return *this; @@ -2201,22 +1919,17 @@ VRegion VRegion::united(const VRect &r) const } else { VRegion result; result.detach(); - PREFIX(_union_rect)(result.d->rgn, d->rgn, - r.left(), r.top(), - r.width(), r.height()); + PREFIX(_union_rect) + (result.d->rgn, d->rgn, r.left(), r.top(), r.width(), r.height()); return result; } } VRegion VRegion::united(const VRegion &r) const { - if (isEmpty()) - return r; - if (r.isEmpty()) - return *this; - if (d == r.d || - PREFIX(_equal)(d->rgn, r.d->rgn)) - return *this; + if (isEmpty()) return r; + if (r.isEmpty()) return *this; + if (d == r.d || PREFIX(_equal)(d->rgn, r.d->rgn)) return *this; VRegion result; result.detach(); PREFIX(_union)(result.d->rgn, d->rgn, r.d->rgn); @@ -2225,29 +1938,24 @@ VRegion VRegion::united(const VRegion &r) const VRegion VRegion::intersected(const VRect &r) const { - if (isEmpty() || r.isEmpty()) - return VRegion(); + if (isEmpty() || r.isEmpty()) return VRegion(); /* this is fully contained in r */ - if (within(r)) - return *this; + if (within(r)) return *this; /* r is fully contained in this */ - if (contains(r)) - return r; + if (contains(r)) return r; VRegion result; result.detach(); - PREFIX(_intersect_rect)(result.d->rgn, d->rgn, - r.left(), r.top(), - r.width(), r.height()); + PREFIX(_intersect_rect) + (result.d->rgn, d->rgn, r.left(), r.top(), r.width(), r.height()); return result; } VRegion VRegion::intersected(const VRegion &r) const { - if (isEmpty() || r.isEmpty()) - return VRegion(); + if (isEmpty() || r.isEmpty()) return VRegion(); VRegion result; result.detach(); @@ -2258,11 +1966,8 @@ VRegion VRegion::intersected(const VRegion &r) const VRegion VRegion::subtracted(const VRegion &r) const { - if (isEmpty() || r.isEmpty()) - return *this; - if (d == r.d || - PREFIX(_equal)(d->rgn, r.d->rgn)) - return VRegion(); + if (isEmpty() || r.isEmpty()) return *this; + if (d == r.d || PREFIX(_equal)(d->rgn, r.d->rgn)) return VRegion(); VRegion result; result.detach(); @@ -2279,8 +1984,7 @@ int VRegion::rectCount() const VRect VRegion::rectAt(int index) const { VRegionPrivate *reg = d->rgn; - if (!reg) - return VRect(); + if (!reg) return VRect(); box_type_t *box = PIXREGION_RECTS(reg) + index; @@ -2288,20 +1992,24 @@ VRect VRegion::rectAt(int index) const } VRegion VRegion::operator+(const VRect &r) const -{ return united(r); } +{ + return united(r); +} VRegion VRegion::operator+(const VRegion &r) const -{ return united(r); } +{ + return united(r); +} VRegion VRegion::operator-(const VRegion &r) const -{ return subtracted(r); } +{ + return subtracted(r); +} -VRegion& VRegion::operator+=(const VRect &r) +VRegion &VRegion::operator+=(const VRect &r) { - if (isEmpty()) - return *this = r; - if (r.isEmpty()) - return *this; + if (isEmpty()) return *this = r; + if (r.isEmpty()) return *this; if (contains(r)) { return *this; @@ -2309,37 +2017,32 @@ VRegion& VRegion::operator+=(const VRect &r) return *this = r; } else { detach(); - PREFIX(_union_rect)(d->rgn, d->rgn, - r.left(), r.top(), - r.width(), r.height()); + PREFIX(_union_rect) + (d->rgn, d->rgn, r.left(), r.top(), r.width(), r.height()); return *this; } } -VRegion& VRegion::operator+=(const VRegion &r) +VRegion &VRegion::operator+=(const VRegion &r) { - if (isEmpty()) - return *this = r; - if (r.isEmpty()) - return *this; - if (d == r.d || - PREFIX(_equal)(d->rgn, r.d->rgn)) - return *this; + if (isEmpty()) return *this = r; + if (r.isEmpty()) return *this; + if (d == r.d || PREFIX(_equal)(d->rgn, r.d->rgn)) return *this; detach(); PREFIX(_union)(d->rgn, d->rgn, r.d->rgn); return *this; } -VRegion& VRegion::operator-=(const VRegion &r) -{ return *this = *this - r; } +VRegion &VRegion::operator-=(const VRegion &r) +{ + return *this = *this - r; +} bool VRegion::operator==(const VRegion &r) const { - if (isEmpty()) - return r.isEmpty(); - if (r.isEmpty()) - return isEmpty(); + if (isEmpty()) return r.isEmpty(); + if (r.isEmpty()) return isEmpty(); if (d == r.d) return true; @@ -2349,8 +2052,7 @@ bool VRegion::operator==(const VRegion &r) const VRect VRegion::boundingRect() const noexcept { - if (isEmpty()) - return VRect(); + if (isEmpty()) return VRect(); return box_to_rect(&d->rgn->extents); } @@ -2362,24 +2064,23 @@ inline bool rect_intersects(const VRect &r1, const VRect &r2) bool VRegion::intersects(const VRegion &r) const { - if (isEmpty() || r.isEmpty()) - return false; + if (isEmpty() || r.isEmpty()) return false; return PREFIX(_intersects)(d->rgn, r.d->rgn); } -VDebug& operator<<(VDebug& os, const VRegion& o) +VDebug &operator<<(VDebug &os, const VRegion &o) { - os<<"[REGION: "<<"[bbox = "< -#include -#include -#include +#include +#include +#include +#include "vdebug.h" V_BEGIN_NAMESPACE struct VRegionData; -class VRegion -{ +class VRegion { public: VRegion(); VRegion(int x, int y, int w, int h); @@ -19,53 +18,54 @@ public: VRegion(const VRegion ®ion); VRegion(VRegion &&other); ~VRegion(); - VRegion &operator=(const VRegion &); - VRegion &operator=(VRegion &&); - bool isEmpty() const; - bool contains(const VRect &r) const; - VRegion united(const VRect &r) const; - VRegion united(const VRegion &r) const; - VRegion intersected(const VRect &r) const; - VRegion intersected(const VRegion &r) const; - VRegion subtracted(const VRegion &r) const; - void translate(const VPoint &p); - inline void translate(int dx, int dy); - VRegion translated(const VPoint &p) const; + VRegion & operator=(const VRegion &); + VRegion & operator=(VRegion &&); + bool isEmpty() const; + bool contains(const VRect &r) const; + VRegion united(const VRect &r) const; + VRegion united(const VRegion &r) const; + VRegion intersected(const VRect &r) const; + VRegion intersected(const VRegion &r) const; + VRegion subtracted(const VRegion &r) const; + void translate(const VPoint &p); + inline void translate(int dx, int dy); + VRegion translated(const VPoint &p) const; inline VRegion translated(int dx, int dy) const; - int rectCount() const; - VRect rectAt(int index) const; + int rectCount() const; + VRect rectAt(int index) const; - VRegion operator+(const VRect &r) const; - VRegion operator+(const VRegion &r) const; - VRegion operator-(const VRegion &r) const; - VRegion& operator+=(const VRect &r); - VRegion& operator+=(const VRegion &r); - VRegion& operator-=(const VRegion &r); + VRegion operator+(const VRect &r) const; + VRegion operator+(const VRegion &r) const; + VRegion operator-(const VRegion &r) const; + VRegion &operator+=(const VRect &r); + VRegion &operator+=(const VRegion &r); + VRegion &operator-=(const VRegion &r); VRect boundingRect() const noexcept; - bool intersects(const VRegion ®ion) const; + bool intersects(const VRegion ®ion) const; - bool operator==(const VRegion &r) const; + bool operator==(const VRegion &r) const; inline bool operator!=(const VRegion &r) const { return !(operator==(r)); } - friend VDebug& operator<<(VDebug& os, const VRegion& o); + friend VDebug &operator<<(VDebug &os, const VRegion &o); + private: - bool within(const VRect &r) const; + bool within(const VRect &r) const; VRegion copy() const; - void detach(); - void cleanUp(VRegionData *x); + void detach(); + void cleanUp(VRegionData *x); struct VRegionData *d; }; inline void VRegion::translate(int dx, int dy) { - translate(VPoint(dx,dy)); + translate(VPoint(dx, dy)); } inline VRegion VRegion::translated(int dx, int dy) const { - return translated(VPoint(dx,dy)); + return translated(VPoint(dx, dy)); } V_END_NAMESPACE -#endif //VREGION_H +#endif // VREGION_H diff --git a/src/vector/vrle.cpp b/src/vector/vrle.cpp index de248a5..83487ac 100644 --- a/src/vector/vrle.cpp +++ b/src/vector/vrle.cpp @@ -1,27 +1,28 @@ #include "vrle.h" -#include"vglobal.h" -#include -#include -#include -#include -#include -#include"vdebug.h" -#include"vregion.h" +#include +#include +#include +#include +#include +#include "vdebug.h" +#include "vglobal.h" +#include "vregion.h" V_BEGIN_NAMESPACE -struct VRleHelper -{ - ushort alloc; - ushort size; - VRle::Span *spans; +struct VRleHelper { + ushort alloc; + ushort size; + VRle::Span *spans; }; -#define VMIN(a,b) ((a) < (b) ? (a) : (b)) -#define VMAX(a,b) ((a) > (b) ? (a) : (b)) +#define VMIN(a, b) ((a) < (b) ? (a) : (b)) +#define VMAX(a, b) ((a) > (b) ? (a) : (b)) -static inline uchar -divBy255(int x) { return (x + (x>>8) + 0x80) >> 8; } +static inline uchar divBy255(int x) +{ + return (x + (x >> 8) + 0x80) >> 8; +} /* * This function will clip a rle list with another rle object @@ -33,86 +34,71 @@ divBy255(int x) { return (x + (x>>8) + 0x80) >> 8; } * that are yet to be processed as well as the tpm_clip object * with the unprocessed clip spans. */ -static void -rleIntersectWithRle(VRleHelper *tmp_clip, - int clip_offset_x, - int clip_offset_y, - VRleHelper *tmp_obj, - VRleHelper *result) +static void rleIntersectWithRle(VRleHelper *tmp_clip, int clip_offset_x, + int clip_offset_y, VRleHelper *tmp_obj, + VRleHelper *result) { VRle::Span *out = result->spans; - int available = result->alloc; + int available = result->alloc; VRle::Span *spans = tmp_obj->spans; VRle::Span *end = tmp_obj->spans + tmp_obj->size; VRle::Span *clipSpans = tmp_clip->spans; VRle::Span *clipEnd = tmp_clip->spans + tmp_clip->size; - int sx1, sx2, cx1, cx2, x, len; - - - while (available && spans < end ) - { - if (clipSpans >= clipEnd) - { - spans = end; - break; - } - if ((clipSpans->y + clip_offset_y) > spans->y) - { - ++spans; - continue; - } - if (spans->y != (clipSpans->y + clip_offset_y)) - { - ++clipSpans; - continue; - } - //assert(spans->y == (clipSpans->y + clip_offset_y)); + int sx1, sx2, cx1, cx2, x, len; + + while (available && spans < end) { + if (clipSpans >= clipEnd) { + spans = end; + break; + } + if ((clipSpans->y + clip_offset_y) > spans->y) { + ++spans; + continue; + } + if (spans->y != (clipSpans->y + clip_offset_y)) { + ++clipSpans; + continue; + } + // assert(spans->y == (clipSpans->y + clip_offset_y)); sx1 = spans->x; sx2 = sx1 + spans->len; cx1 = (clipSpans->x + clip_offset_x); cx2 = cx1 + clipSpans->len; - if (cx1 < sx1 && cx2 < sx1) - { - ++clipSpans; - continue; - } - else if (sx1 < cx1 && sx2 < cx1) - { - ++spans; - continue; - } + if (cx1 < sx1 && cx2 < sx1) { + ++clipSpans; + continue; + } else if (sx1 < cx1 && sx2 < cx1) { + ++spans; + continue; + } x = VMAX(sx1, cx1); len = VMIN(sx2, cx2) - x; - if (len) - { - out->x = VMAX(sx1, cx1); - out->len = ( VMIN(sx2, cx2) - out->x); - out->y = spans->y; - out->coverage = divBy255(spans->coverage * clipSpans->coverage); - ++out; - --available; - } - if (sx2 < cx2) - { - ++spans; - } - else - { - ++clipSpans; - } - } - - // update the span list that yet to be processed - tmp_obj->spans = spans; - tmp_obj->size = end - spans; - - // update the clip list that yet to be processed - tmp_clip->spans = clipSpans; - tmp_clip->size = clipEnd - clipSpans; - - // update the result - result->size = result->alloc - available; + if (len) { + out->x = VMAX(sx1, cx1); + out->len = (VMIN(sx2, cx2) - out->x); + out->y = spans->y; + out->coverage = divBy255(spans->coverage * clipSpans->coverage); + ++out; + --available; + } + if (sx2 < cx2) { + ++spans; + } else { + ++clipSpans; + } + } + + // update the span list that yet to be processed + tmp_obj->spans = spans; + tmp_obj->size = end - spans; + + // update the clip list that yet to be processed + tmp_clip->spans = clipSpans; + tmp_clip->size = clipEnd - clipSpans; + + // update the result + result->size = result->alloc - available; } /* @@ -124,62 +110,52 @@ rleIntersectWithRle(VRleHelper *tmp_clip, * it will stop and update the tmp_obj with the span list * that are yet to be processed */ -static void -rleIntersectWithRect(const VRect &clip, - VRleHelper *tmp_obj, - VRleHelper *result) -{ - VRle::Span *out = result->spans; - int available = result->alloc; - VRle::Span *spans = tmp_obj->spans; - VRle::Span *end = tmp_obj->spans + tmp_obj->size; - short minx, miny, maxx, maxy; - - minx = clip.left(); - miny = clip.top(); - maxx = clip.right() - 1; - maxy = clip.bottom() - 1; - - while (available && spans < end ) - { - if (spans->y > maxy) - { - spans = end;// update spans so that we can breakout - break; - } - if (spans->y < miny - || spans->x > maxx - || spans->x + spans->len <= minx) - { - ++spans; - continue; - } - if (spans->x < minx) - { - out->len = VMIN(spans->len - (minx - spans->x), maxx - minx + 1); - out->x = minx; - } - else - { - out->x = spans->x; - out->len = VMIN(spans->len, (maxx - spans->x + 1)); - } - if (out->len != 0) - { - out->y = spans->y; - out->coverage = spans->coverage; - ++out; - --available; - } +static void rleIntersectWithRect(const VRect &clip, VRleHelper *tmp_obj, + VRleHelper *result) +{ + VRle::Span *out = result->spans; + int available = result->alloc; + VRle::Span *spans = tmp_obj->spans; + VRle::Span *end = tmp_obj->spans + tmp_obj->size; + short minx, miny, maxx, maxy; + + minx = clip.left(); + miny = clip.top(); + maxx = clip.right() - 1; + maxy = clip.bottom() - 1; + + while (available && spans < end) { + if (spans->y > maxy) { + spans = end; // update spans so that we can breakout + break; + } + if (spans->y < miny || spans->x > maxx || + spans->x + spans->len <= minx) { + ++spans; + continue; + } + if (spans->x < minx) { + out->len = VMIN(spans->len - (minx - spans->x), maxx - minx + 1); + out->x = minx; + } else { + out->x = spans->x; + out->len = VMIN(spans->len, (maxx - spans->x + 1)); + } + if (out->len != 0) { + out->y = spans->y; + out->coverage = spans->coverage; + ++out; + --available; + } ++spans; - } + } - // update the span list that yet to be processed - tmp_obj->spans = spans; - tmp_obj->size = end - spans; + // update the span list that yet to be processed + tmp_obj->spans = spans; + tmp_obj->size = end - spans; - // update the result - result->size = result->alloc - available; + // update the result + result->size = result->alloc - available; } void drawSpanlineMul(VRle::Span *spans, int count, uchar *buffer, int offsetX) @@ -213,10 +189,10 @@ void drawSpanline(VRle::Span *spans, int count, uchar *buffer, int offsetX) int bufferToRle(uchar *buffer, int size, int offsetX, int y, VRle::Span *out) { - int count = 0; + int count = 0; uchar value = buffer[0]; - int curIndex = 0; - for (int i = 0; i < size ; i++) { + int curIndex = 0; + for (int i = 0; i < size; i++) { uchar curValue = buffer[0]; if (value != curValue) { out->y = y; @@ -238,18 +214,16 @@ int bufferToRle(uchar *buffer, int size, int offsetX, int y, VRle::Span *out) return count; } -static void -rleAddWithRle1(VRleHelper *tmp_clip, - VRleHelper *tmp_obj, - VRleHelper *result) +static void rleAddWithRle1(VRleHelper *tmp_clip, VRleHelper *tmp_obj, + VRleHelper *result) { - std::array rleHolder; - VRle::Span *out = result->spans; - int available = result->alloc; - VRle::Span *spans = tmp_obj->spans; - VRle::Span *end = tmp_obj->spans + tmp_obj->size; - VRle::Span *clipSpans = tmp_clip->spans; - VRle::Span *clipEnd = tmp_clip->spans + tmp_clip->size; + std::array rleHolder; + VRle::Span * out = result->spans; + int available = result->alloc; + VRle::Span * spans = tmp_obj->spans; + VRle::Span * end = tmp_obj->spans + tmp_obj->size; + VRle::Span * clipSpans = tmp_clip->spans; + VRle::Span * clipEnd = tmp_clip->spans + tmp_clip->size; while (available && spans < end && clipSpans < clipEnd) { if (spans->y < clipSpans->y) { @@ -258,25 +232,27 @@ rleAddWithRle1(VRleHelper *tmp_clip, } else if (clipSpans->y < spans->y) { *out++ = *clipSpans++; available--; - } else { // same y - int y = spans->y; + } else { // same y + int y = spans->y; VRle::Span *spanPtr = spans; VRle::Span *clipPtr = clipSpans; while (spanPtr < end && spanPtr->y == y) spanPtr++; while (clipPtr < clipEnd && clipPtr->y == y) clipPtr++; - int spanLength = (spanPtr-1)->x + (spanPtr-1)->len - spans->x; - int clipLength = (clipPtr-1)->x + (clipPtr-1)->len - clipSpans->x; - int offsetX = VMIN(spans->x, clipSpans->x); - std::array array = {0}; + int spanLength = (spanPtr - 1)->x + (spanPtr - 1)->len - spans->x; + int clipLength = + (clipPtr - 1)->x + (clipPtr - 1)->len - clipSpans->x; + int offsetX = VMIN(spans->x, clipSpans->x); + std::array array = {0}; drawSpanline(spans, (spanPtr - spans), array.data(), -offsetX); - drawSpanlineMul(clipSpans, (clipPtr - clipSpans), array.data(), -offsetX); + drawSpanlineMul(clipSpans, (clipPtr - clipSpans), array.data(), + -offsetX); VRle::Span *rleHolderPtr = rleHolder.data(); int size = bufferToRle(array.data(), VMAX(spanLength, clipLength), offsetX, y, rleHolderPtr); if (available >= size) { - while(size--) { + while (size--) { *out++ = *rleHolderPtr++; available--; } @@ -299,47 +275,48 @@ rleAddWithRle1(VRleHelper *tmp_clip, result->size = result->alloc - available; } - -class VRleImpl -{ +class VRleImpl { public: - inline VRleImpl():m_bbox(),m_spans(), mOffset(), mBboxDirty(true){} + inline VRleImpl() : m_bbox(), m_spans(), mOffset(), mBboxDirty(true) {} VRleImpl &operator=(const VRleImpl &); - void addSpan(const VRle::Span *span, int count); - void updateBbox(); - bool operator ==(const VRleImpl &) const; - void intersected(const VRect &r, VRleImpl &result); + void addSpan(const VRle::Span *span, int count); + void updateBbox(); + bool operator==(const VRleImpl &) const; + void intersected(const VRect &r, VRleImpl &result); void intersect(const VRect &r, VRle::VRleSpanCb cb, void *userData) const; void intersected(const VRleImpl &clip, VRleImpl &result); - friend VDebug& operator<<(VDebug& os, const VRleImpl& object); - void invert(); - void alphaMul(int alpha); - void translate(const VPoint &pt); - void opAdd(const VRleImpl &other, VRleImpl &res); - VRect bbox(); + friend VDebug &operator<<(VDebug &os, const VRleImpl &object); + void invert(); + void alphaMul(int alpha); + void translate(const VPoint &pt); + void opAdd(const VRleImpl &other, VRleImpl &res); + VRect bbox(); + public: VRect m_bbox; - std::vector m_spans;// array of Spanlines. + std::vector m_spans; // array of Spanlines. VPoint mOffset; - bool mBboxDirty; + bool mBboxDirty; }; -inline static void -copyArrayToVector(const VRle::Span *span, int count, std::vector &v) +inline static void copyArrayToVector(const VRle::Span *span, int count, + std::vector &v) { // make sure enough memory available v.reserve(v.size() + count); std::copy(span, span + count, back_inserter(v)); } -VDebug& operator<<(VDebug& os, const VRleImpl& o) +VDebug &operator<<(VDebug &os, const VRleImpl &o) { - os<<"[bbox="<< o.m_bbox<<"]"<<"[offset="< array; + VRleHelper tresult, tmp_obj; + std::array array; - //setup the tresult object + // setup the tresult object tresult.size = array.size(); tresult.alloc = array.size(); tresult.spans = array.data(); @@ -396,25 +373,25 @@ void VRleImpl::intersected(const VRect &r, VRleImpl &result) tmp_obj.spans = m_spans.data(); // run till all the spans are processed - while (tmp_obj.size) - { - rleIntersectWithRect(clip, &tmp_obj, &tresult); - if (tresult.size) { - copyArrayToVector(tresult.spans, tresult.size, result.m_spans); - } - tresult.size = 0; - } + while (tmp_obj.size) { + rleIntersectWithRect(clip, &tmp_obj, &tresult); + if (tresult.size) { + copyArrayToVector(tresult.spans, tresult.size, result.m_spans); + } + tresult.size = 0; + } result.updateBbox(); } -void VRleImpl::intersect(const VRect &r, VRle::VRleSpanCb cb, void *userData) const +void VRleImpl::intersect(const VRect &r, VRle::VRleSpanCb cb, + void *userData) const { VRect clip = r; - VRleHelper tresult, tmp_obj; - std::array array; + VRleHelper tresult, tmp_obj; + std::array array; - //setup the tresult object + // setup the tresult object tresult.size = array.size(); tresult.alloc = array.size(); tresult.spans = array.data(); @@ -424,22 +401,21 @@ void VRleImpl::intersect(const VRect &r, VRle::VRleSpanCb cb, void *userData) co tmp_obj.spans = const_cast(m_spans.data()); // run till all the spans are processed - while (tmp_obj.size) - { - rleIntersectWithRect(clip, &tmp_obj, &tresult); - if (tresult.size) { - cb(tresult.size, tresult.spans, userData); - } - tresult.size = 0; - } + while (tmp_obj.size) { + rleIntersectWithRect(clip, &tmp_obj, &tresult); + if (tresult.size) { + cb(tresult.size, tresult.spans, userData); + } + tresult.size = 0; + } } void VRleImpl::intersected(const VRleImpl &clip, VRleImpl &result) { - VRleHelper tresult, tmp_obj, tmp_clip; - std::array array; + VRleHelper tresult, tmp_obj, tmp_clip; + std::array array; - //setup the tresult object + // setup the tresult object tresult.size = array.size(); tresult.alloc = array.size(); tresult.spans = array.data(); @@ -448,19 +424,18 @@ void VRleImpl::intersected(const VRleImpl &clip, VRleImpl &result) tmp_obj.size = m_spans.size(); tmp_obj.spans = m_spans.data(); - //setup tmp clip object + // setup tmp clip object tmp_clip.size = clip.m_spans.size(); tmp_clip.spans = const_cast(clip.m_spans.data()); // run till all the spans are processed - while (tmp_obj.size) - { - rleIntersectWithRle(&tmp_clip, 0, 0, &tmp_obj, &tresult); - if (tresult.size) { - copyArrayToVector(tresult.spans, tresult.size, result.m_spans); - } - tresult.size = 0; - } + while (tmp_obj.size) { + rleIntersectWithRle(&tmp_clip, 0, 0, &tmp_obj, &tresult); + if (tresult.size) { + copyArrayToVector(tresult.spans, tresult.size, result.m_spans); + } + tresult.size = 0; + } result.updateBbox(); } @@ -471,20 +446,21 @@ void VRleImpl::opAdd(const VRleImpl &other, VRleImpl &result) // if two rle are disjoint if (!m_bbox.intersects(other.m_bbox)) { result.m_spans = m_spans; - copyArrayToVector(other.m_spans.data(), other.m_spans.size(), result.m_spans); + copyArrayToVector(other.m_spans.data(), other.m_spans.size(), + result.m_spans); } else { VRle::Span *ptr = m_spans.data(); - int otherY = other.m_bbox.top(); + int otherY = other.m_bbox.top(); // 1. forward till both y intersect - while (ptr->y < otherY) ptr++; + while (ptr->y < otherY) ptr++; int spanToCopy = ptr - m_spans.data(); copyArrayToVector(m_spans.data(), spanToCopy, result.m_spans); // 2. calculate the intersect region - VRleHelper tresult, tmp_obj, tmp_other; - std::array array; + VRleHelper tresult, tmp_obj, tmp_other; + std::array array; - //setup the tresult object + // setup the tresult object tresult.size = array.size(); tresult.alloc = array.size(); tresult.spans = array.data(); @@ -493,20 +469,19 @@ void VRleImpl::opAdd(const VRleImpl &other, VRleImpl &result) tmp_obj.size = m_spans.size() - spanToCopy; tmp_obj.spans = ptr; - //setup tmp clip object + // setup tmp clip object tmp_other.size = other.m_spans.size(); tmp_other.spans = const_cast(other.m_spans.data()); // run till all the spans are processed - while (tmp_obj.size && tmp_other.size) - { - rleAddWithRle1(&tmp_other, &tmp_obj, &tresult); - if (tresult.size) { - copyArrayToVector(tresult.spans, tresult.size, result.m_spans); - } - tresult.size = 0; - } - //3. copy the rest + while (tmp_obj.size && tmp_other.size) { + rleAddWithRle1(&tmp_other, &tmp_obj, &tresult); + if (tresult.size) { + copyArrayToVector(tresult.spans, tresult.size, result.m_spans); + } + tresult.size = 0; + } + // 3. copy the rest if (tmp_other.size) { copyArrayToVector(tmp_other.spans, tmp_other.size, result.m_spans); } @@ -522,7 +497,6 @@ void VRleImpl::opAdd(const VRleImpl &other, VRleImpl &result) result.mBboxDirty = false; } - VRleImpl &VRleImpl::operator=(const VRleImpl &other) { m_spans = other.m_spans; @@ -531,17 +505,15 @@ VRleImpl &VRleImpl::operator=(const VRleImpl &other) return *this; } -bool VRleImpl::operator ==(const VRleImpl &other) const +bool VRleImpl::operator==(const VRleImpl &other) const { - if (m_spans.size() != other.m_spans.size()) - return false; + if (m_spans.size() != other.m_spans.size()) return false; const VRle::Span *spans = m_spans.data(); const VRle::Span *o_spans = other.m_spans.data(); - int sz = m_spans.size(); + int sz = m_spans.size(); for (int i = 0; i < sz; i++) { - if (spans[i].x != o_spans[i].x || - spans[i].y != o_spans[i].y || + if (spans[i].x != o_spans[i].x || spans[i].y != o_spans[i].y || spans[i].len != o_spans[i].len || spans[i].coverage != o_spans[i].coverage) return false; @@ -549,7 +521,6 @@ bool VRleImpl::operator ==(const VRleImpl &other) const return true; } - void VRleImpl::updateBbox() { if (!mBboxDirty) return; @@ -562,17 +533,15 @@ void VRleImpl::updateBbox() m_bbox = VRect(); sz = m_spans.size(); - if (sz) - { - t = span[0].y; - b = span[sz-1].y; - for (i = 0; i < sz; i++) - { - if (span[i].x < l) l = span[i].x; - if (span[i].x + span[i].len > r) r = span[i].x + span[i].len; - } - m_bbox = VRect(l, t, r - l, b - t + 1); - } + if (sz) { + t = span[0].y; + b = span[sz - 1].y; + for (i = 0; i < sz; i++) { + if (span[i].x < l) l = span[i].x; + if (span[i].x + span[i].len > r) r = span[i].x + span[i].len; + } + m_bbox = VRect(l, t, r - l, b - t + 1); + } } void VRleImpl::addSpan(const VRle::Span *span, int count) @@ -581,11 +550,10 @@ void VRleImpl::addSpan(const VRle::Span *span, int count) mBboxDirty = true; } -struct VRleData -{ - VRleData():ref(-1), impl(){} - RefCount ref; - VRleImpl impl; +struct VRleData { + VRleData() : ref(-1), impl() {} + RefCount ref; + VRleImpl impl; }; static const struct VRleData shared_empty; @@ -597,8 +565,7 @@ inline void VRle::cleanUp(VRleData *d) void VRle::detach() { - if (d->ref.isShared()) - *this = copy(); + if (d->ref.isShared()) *this = copy(); } VRle VRle::copy() const @@ -613,14 +580,10 @@ VRle VRle::copy() const VRle::~VRle() { - if (!d->ref.deref()) - cleanUp(d); + if (!d->ref.deref()) cleanUp(d); } -VRle::VRle() - : d(const_cast(&shared_empty)) -{ -} +VRle::VRle() : d(const_cast(&shared_empty)) {} VRle::VRle(const VRle &other) { @@ -628,16 +591,15 @@ VRle::VRle(const VRle &other) d->ref.ref(); } -VRle::VRle(VRle &&other): d(other.d) +VRle::VRle(VRle &&other) : d(other.d) { - other.d = const_cast(&shared_empty); + other.d = const_cast(&shared_empty); } VRle &VRle::operator=(const VRle &other) { other.d->ref.ref(); - if (!d->ref.deref()) - cleanUp(d); + if (!d->ref.deref()) cleanUp(d); d = other.d; return *this; @@ -645,14 +607,13 @@ VRle &VRle::operator=(const VRle &other) inline VRle &VRle::operator=(VRle &&other) { - if (!d->ref.deref()) - cleanUp(d); + if (!d->ref.deref()) cleanUp(d); d = other.d; - other.d = const_cast(&shared_empty); + other.d = const_cast(&shared_empty); return *this; } -bool VRle::isEmpty()const +bool VRle::isEmpty() const { return (d == &shared_empty || d->impl.m_spans.empty()); } @@ -665,17 +626,14 @@ void VRle::addSpan(const VRle::Span *span, int count) VRect VRle::boundingRect() const { - if(isEmpty()) - return VRect(); + if (isEmpty()) return VRect(); return d->impl.bbox(); } -bool VRle::operator ==(const VRle &other) const +bool VRle::operator==(const VRle &other) const { - if (isEmpty()) - return other.isEmpty(); - if (other.isEmpty()) - return isEmpty(); + if (isEmpty()) return other.isEmpty(); + if (other.isEmpty()) return isEmpty(); if (d == other.d) return true; @@ -695,12 +653,10 @@ void VRle::translate(const VPoint &p) VRle VRle::intersected(const VRect &r) const { - if (isEmpty() || r.isEmpty()) - return VRle(); + if (isEmpty() || r.isEmpty()) return VRle(); // check if the bounding rect is contain inside r - if (r.contains(boundingRect(), true)) - return *this; + if (r.contains(boundingRect(), true)) return *this; VRle result; result.detach(); @@ -710,8 +666,7 @@ VRle VRle::intersected(const VRect &r) const VRle VRle::intersected(const VRle &other) const { - if (isEmpty() || other.isEmpty()) - return VRle(); + if (isEmpty() || other.isEmpty()) return VRle(); // check if the bounding rect are not intersecting VRle result; result.detach(); @@ -738,7 +693,7 @@ VRle VRle::operator+(const VRle &other) const VRle result; result.detach(); if (boundingRect().top() < other.boundingRect().top()) - d->impl.opAdd(other.d->impl, result.d->impl); + d->impl.opAdd(other.d->impl, result.d->impl); else other.d->impl.opAdd(d->impl, result.d->impl); return result; @@ -766,18 +721,14 @@ VRle VRle::operator&(const VRle &o) const return result; } - - void VRle::intersect(const VRect &r, VRleSpanCb cb, void *userData) const { d->impl.intersect(r, cb, userData); } - -VRle &VRle::intersect(const VRect &r) +VRle &VRle::intersect(const VRect &r) { - if (isEmpty() || r.isEmpty()) - return *this = VRle(); + if (isEmpty() || r.isEmpty()) return *this = VRle(); VRle result; result.detach(); @@ -795,14 +746,13 @@ VRle operator*(const VRle &obj, int alpha) return result; } - int VRle::size() const { if (isEmpty()) return 0; return d->impl.m_spans.size(); } -const VRle::Span* VRle::data() const +const VRle::Span *VRle::data() const { if (isEmpty()) return nullptr; return d->impl.m_spans.data(); @@ -820,24 +770,23 @@ VRle VRle::toRle(const VRect &rect) int height = rect.height(); result.d->impl.m_spans.reserve(height); VRle::Span span; - for(int i=0; i < height ; i++) { + for (int i = 0; i < height; i++) { span.x = x; span.y = y + i; span.len = width; span.coverage = 255; - result.d->impl.m_spans.push_back(span); + result.d->impl.m_spans.push_back(span); } return result; } -VDebug& operator<<(VDebug& os, const VRle& o) +VDebug &operator<<(VDebug &os, const VRle &o) { - os<<"[RLE: [dptr = "<<"o.d"<<"]"<<"[ref = "<ref.count()<<"]"<impl<<"]"; + os << "[RLE: [dptr = " + << "o.d" + << "]" + << "[ref = " << o.d->ref.count() << "]" << o.d->impl << "]"; return os; } V_END_NAMESPACE - - - - diff --git a/src/vector/vrle.h b/src/vector/vrle.h index fd7ca29..5b0e003 100644 --- a/src/vector/vrle.h +++ b/src/vector/vrle.h @@ -1,59 +1,59 @@ #ifndef VRLE_H #define VRLE_H -#include -#include -#include +#include +#include +#include V_BEGIN_NAMESPACE struct VRleData; -class VRle -{ +class VRle { public: - struct Span - { - short x; - short y; - ushort len; - uchar coverage; + struct Span { + short x; + short y; + ushort len; + uchar coverage; }; - typedef void (*VRleSpanCb)(int count, const VRle::Span *spans, void *userData); + typedef void (*VRleSpanCb)(int count, const VRle::Span *spans, + void *userData); ~VRle(); VRle(); VRle(const VRle &other); VRle(VRle &&other); VRle &operator=(const VRle &); VRle &operator=(VRle &&other); - bool isEmpty()const; + bool isEmpty() const; VRect boundingRect() const; - void addSpan(const VRle::Span *span, int count); - bool operator ==(const VRle &other) const; - void translate(const VPoint &p); - void translate(int x, int y); - VRle intersected(const VRect &r) const; - VRle intersected(const VRle &other) const; - void intersect(const VRect &r, VRleSpanCb cb, void *userData) const; + void addSpan(const VRle::Span *span, int count); + bool operator==(const VRle &other) const; + void translate(const VPoint &p); + void translate(int x, int y); + VRle intersected(const VRect &r) const; + VRle intersected(const VRle &other) const; + void intersect(const VRect &r, VRleSpanCb cb, void *userData) const; VRle &intersect(const VRect &r); - int size() const; - const VRle::Span* data() const; - VRle operator~() const; - VRle operator+(const VRle &o) const; - VRle operator-(const VRle &o) const; - VRle operator&(const VRle &o) const; - static VRle toRle(const VRect &rect); - friend VRle operator*(const VRle &, int alpha); + int size() const; + const VRle::Span * data() const; + VRle operator~() const; + VRle operator+(const VRle &o) const; + VRle operator-(const VRle &o) const; + VRle operator&(const VRle &o) const; + static VRle toRle(const VRect &rect); + friend VRle operator*(const VRle &, int alpha); inline friend VRle operator*(int alpha, const VRle &); - friend VDebug& operator<<(VDebug& os, const VRle& object); + friend VDebug & operator<<(VDebug &os, const VRle &object); + private: - VRle copy() const; - void detach(); - void cleanUp(VRleData *x); + VRle copy() const; + void detach(); + void cleanUp(VRleData *x); VRleData *d; }; inline void VRle::translate(int x, int y) { - translate(VPoint(x,y)); + translate(VPoint(x, y)); } inline VRle operator*(int alpha, const VRle &rle) @@ -63,4 +63,4 @@ inline VRle operator*(int alpha, const VRle &rle) V_END_NAMESPACE -#endif // VRLE_H +#endif // VRLE_H diff --git a/src/vector/vtaskqueue.h b/src/vector/vtaskqueue.h index 66bb693..5700eab 100644 --- a/src/vector/vtaskqueue.h +++ b/src/vector/vtaskqueue.h @@ -1,18 +1,19 @@ #ifndef VTASKQUEUE_H #define VTASKQUEUE_H -#include +#include template class TaskQueue { using lock_t = std::unique_lock; - std::deque _q; - bool _done{false}; - std::mutex _mutex; + std::deque _q; + bool _done{false}; + std::mutex _mutex; std::condition_variable _ready; public: - bool try_pop(Task *&task) { + bool try_pop(Task *&task) + { lock_t lock{_mutex, std::try_to_lock}; if (!lock || _q.empty()) return false; task = _q.front(); @@ -20,7 +21,8 @@ public: return true; } - bool try_push(Task *task) { + bool try_push(Task *task) + { { lock_t lock{_mutex, std::try_to_lock}; if (!lock) return false; @@ -30,7 +32,8 @@ public: return true; } - void done() { + void done() + { { lock_t lock{_mutex}; _done = true; @@ -38,17 +41,18 @@ public: _ready.notify_all(); } - bool pop(Task *&task) { + bool pop(Task *&task) + { lock_t lock{_mutex}; - while (_q.empty() && !_done) - _ready.wait(lock); + while (_q.empty() && !_done) _ready.wait(lock); if (_q.empty()) return false; task = _q.front(); _q.pop_front(); return true; } - void push(Task *task) { + void push(Task *task) + { { lock_t lock{_mutex}; _q.push_back(task); @@ -57,4 +61,4 @@ public: } }; -#endif // VTASKQUEUE_H +#endif // VTASKQUEUE_H