#ifndef LOTPLAYER_H
#define LOTPLAYER_H
-#include <vector>
#include <future>
+#include <vector>
#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;
bool clear;
};
-class LOT_EXPORT LOTPlayer
-{
+class LOT_EXPORT LOTPlayer {
public:
~LOTPlayer();
LOTPlayer();
float playTime() const;
- void setPos(float pos);
+ void setPos(float pos);
float pos();
- const std::vector<LOTNode *>& renderList() const;
+ const std::vector<LOTNode *> &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<bool> 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;
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
#include "lottieitem.h"
-#include"vbitmap.h"
-#include"vpainter.h"
-#include"vraster.h"
-#include"vdasher.h"
#include <cmath>
+#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<LOTLayerData *>(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<LOTLayerData *>(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<LOTDrawable *>(i);
lotDrawable->sync();
mRenderList.push_back(&lotDrawable->mCNode);
}
}
-const std::vector<LOTNode *>& LOTCompItem::renderList() const
+const std::vector<LOTNode *> &LOTCompItem::renderList() const
{
return mRenderList;
}
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.
*/
}
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;
mRle = mRleTask.get();
if (!vCompare(mCombinedAlpha, 1.0f))
mRle = mRle * (mCombinedAlpha * 255);
- if (mData->mInv)
- mRle = ~mRle;
+ if (mData->mInv) mRle = ~mRle;
}
return mRle;
}
mask = mask & inheritMask;
}
- for(auto i : list) {
+ for (auto i : list) {
painter->setBrush(i->mBrush);
if (!mask.isEmpty()) {
VRle rle = i->rle() & mask;
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) {
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<LOTLayerData *>(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<LOTLayerData *>(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();
}
}
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;
}
}
{
// 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());
}
}
// 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<LOTDrawable>();
- 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<LOTDrawable>();
+ 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<VDrawable *> &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()
delete mRoot;
}
-LOTContentItem * LOTShapeLayerItem::createContentItem(LOTData *contentData)
+LOTContentItem *LOTShapeLayerItem::createContentItem(LOTData *contentData)
{
- switch(contentData->type()) {
- case LOTData::Type::ShapeGroup: {
- return new LOTContentGroupItem(static_cast<LOTShapeGroupData *>(contentData));
- break;
- }
- case LOTData::Type::Rect: {
- return new LOTRectItem(static_cast<LOTRectData *>(contentData));
- break;
- }
- case LOTData::Type::Ellipse: {
- return new LOTEllipseItem(static_cast<LOTEllipseData *>(contentData));
- break;
- }
- case LOTData::Type::Shape: {
- return new LOTShapeItem(static_cast<LOTShapeData *>(contentData));
- break;
- }
- case LOTData::Type::Polystar: {
- return new LOTPolystarItem(static_cast<LOTPolystarData *>(contentData));
- break;
- }
- case LOTData::Type::Fill: {
- return new LOTFillItem(static_cast<LOTFillData *>(contentData));
- break;
- }
- case LOTData::Type::GFill: {
- return new LOTGFillItem(static_cast<LOTGFillData *>(contentData));
- break;
- }
- case LOTData::Type::Stroke: {
- return new LOTStrokeItem(static_cast<LOTStrokeData *>(contentData));
- break;
- }
- case LOTData::Type::GStroke: {
- return new LOTGStrokeItem(static_cast<LOTGStrokeData *>(contentData));
- break;
- }
- case LOTData::Type::Repeater: {
- return new LOTRepeaterItem(static_cast<LOTRepeaterData *>(contentData));
- break;
- }
- case LOTData::Type::Trim: {
- return new LOTTrimItem(static_cast<LOTTrimData *>(contentData));
- break;
- }
- default:
- return nullptr;
- break;
+ switch (contentData->type()) {
+ case LOTData::Type::ShapeGroup: {
+ return new LOTContentGroupItem(
+ static_cast<LOTShapeGroupData *>(contentData));
+ break;
+ }
+ case LOTData::Type::Rect: {
+ return new LOTRectItem(static_cast<LOTRectData *>(contentData));
+ break;
+ }
+ case LOTData::Type::Ellipse: {
+ return new LOTEllipseItem(static_cast<LOTEllipseData *>(contentData));
+ break;
+ }
+ case LOTData::Type::Shape: {
+ return new LOTShapeItem(static_cast<LOTShapeData *>(contentData));
+ break;
+ }
+ case LOTData::Type::Polystar: {
+ return new LOTPolystarItem(static_cast<LOTPolystarData *>(contentData));
+ break;
+ }
+ case LOTData::Type::Fill: {
+ return new LOTFillItem(static_cast<LOTFillData *>(contentData));
+ break;
+ }
+ case LOTData::Type::GFill: {
+ return new LOTGFillItem(static_cast<LOTGFillData *>(contentData));
+ break;
+ }
+ case LOTData::Type::Stroke: {
+ return new LOTStrokeItem(static_cast<LOTStrokeData *>(contentData));
+ break;
+ }
+ case LOTData::Type::GStroke: {
+ return new LOTGStrokeItem(static_cast<LOTGStrokeData *>(contentData));
+ break;
+ }
+ case LOTData::Type::Repeater: {
+ return new LOTRepeaterItem(static_cast<LOTRepeaterData *>(contentData));
+ break;
+ }
+ case LOTData::Type::Trim: {
+ return new LOTTrimItem(static_cast<LOTTrimData *>(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<VDrawable *> &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<VDrawable *> &list)
{
for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) {
- (*i)->renderList(list);
+ (*i)->renderList(list);
}
}
void LOTContentGroupItem::processPaintOperation()
{
- std::vector<LOTPaintDataItem *> list;
- paintOperationHelper(list);
+ std::vector<LOTPaintDataItem *> list;
+ paintOperationHelper(list);
}
-void LOTContentGroupItem::paintOperationHelper(std::vector<LOTPaintDataItem *> &list)
+void LOTContentGroupItem::paintOperationHelper(
+ std::vector<LOTPaintDataItem *> &list)
{
- int curOpCount = list.size();
- for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) {
- auto child = *i;
- if (auto pathNode = dynamic_cast<LOTPathDataItem *>(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<LOTPaintDataItem *>(child)) {
- // add it to the paint operation list
- list.push_back(paintNode);
- } else if (auto groupNode = dynamic_cast<LOTContentGroupItem *>(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<LOTPathDataItem *>(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<LOTPaintDataItem *>(child)) {
+ // add it to the paint operation list
+ list.push_back(paintNode);
+ } else if (auto groupNode =
+ dynamic_cast<LOTContentGroupItem *>(child)) {
+ // update the groups node with current list
+ groupNode->paintOperationHelper(list);
+ }
+ }
+ list.erase(list.begin() + curOpCount, list.end());
}
-void LOTPathDataItem::addPaintOperation(std::vector<LOTPaintDataItem *> &list, int externalCount)
+void LOTPathDataItem::addPaintOperation(std::vector<LOTPaintDataItem *> &list,
+ int externalCount)
{
- for(auto paintItem : list) {
- bool sameGroup = (externalCount-- > 0) ? false : true;
- mNodeList.push_back(std::make_unique<LOTDrawable>());
- 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<LOTDrawable>());
+ mRenderList.push_back(
+ LOTRenderNode(this, paintItem, mNodeList.back().get(), sameGroup));
}
}
void LOTContentGroupItem::processTrimOperation()
{
- std::vector<LOTTrimItem *> list;
- trimOperationHelper(list);
+ std::vector<LOTTrimItem *> list;
+ trimOperationHelper(list);
}
void LOTContentGroupItem::trimOperationHelper(std::vector<LOTTrimItem *> &list)
{
- int curOpCount = list.size();
- for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) {
- auto child = *i;
- if (auto pathNode = dynamic_cast<LOTPathDataItem *>(child)) {
- // the node is a path data node add the trim operation list to it.
- pathNode->addTrimOperation(list);
- } else if (auto trimNode = dynamic_cast<LOTTrimItem *>(child)) {
- // add it to the trim operation list
- list.push_back(trimNode);
- } else if (auto groupNode = dynamic_cast<LOTContentGroupItem *>(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<LOTPathDataItem *>(child)) {
+ // the node is a path data node add the trim operation list to it.
+ pathNode->addTrimOperation(list);
+ } else if (auto trimNode = dynamic_cast<LOTTrimItem *>(child)) {
+ // add it to the trim operation list
+ list.push_back(trimNode);
+ } else if (auto groupNode =
+ dynamic_cast<LOTContentGroupItem *>(child)) {
+ // update the groups node with current list
+ groupNode->trimOperationHelper(list);
+ }
+ }
+ list.erase(list.begin() + curOpCount, list.end());
}
void LOTPathDataItem::addTrimOperation(std::vector<LOTTrimItem *> &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<VDrawable *> &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)
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)
{
}
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;
}
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();
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;
}
}
}
-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<VDrawable *> &list)
-{
-
-}
+void LOTRepeaterItem::renderList(std::vector<VDrawable *> &list) {}
void LOTDrawable::sync()
{
if (mFlag & DirtyState::Path) {
const std::vector<VPath::Element> &elm = mPath.elements();
- const std::vector<VPointF> &pts = mPath.points();
+ const std::vector<VPointF> & pts = mPath.points();
const float *ptPtr = reinterpret_cast<const float *>(pts.data());
- const char *elmPtr = reinterpret_cast<const char *>(elm.data());
+ const char * elmPtr = reinterpret_cast<const char *>(elm.data());
mCNode.mPath.elmPtr = elmPtr;
mCNode.mPath.elmCount = elm.size();
mCNode.mPath.ptPtr = ptPtr;
break;
}
}
-
-
#include "lottieloader.h"
#include "lottieparser.h"
-#include<fstream>
-#include<unordered_map>
+#include <fstream>
+#include <unordered_map>
using namespace std;
-class LottieFileCache
-{
+class LottieFileCache {
public:
- ~LottieFileCache();
- static LottieFileCache &get() {
- static LottieFileCache CACHE;
-
- return CACHE;
- }
- std::shared_ptr<LOTModel> find(std::string &key);
- void add(std::string &key, std::shared_ptr<LOTModel> value);
-private:
- LottieFileCache(){}
+ ~LottieFileCache();
+ static LottieFileCache &get()
+ {
+ static LottieFileCache CACHE;
+
+ return CACHE;
+ }
+ std::shared_ptr<LOTModel> find(std::string &key);
+ void add(std::string &key, std::shared_ptr<LOTModel> value);
- std::unordered_map<std::string, std::shared_ptr<LOTModel>> mHash;
+private:
+ LottieFileCache() {}
+ std::unordered_map<std::string, std::shared_ptr<LOTModel>> mHash;
};
-LottieFileCache::~LottieFileCache()
+LottieFileCache::~LottieFileCache() {}
+std::shared_ptr<LOTModel> LottieFileCache::find(std::string &key)
{
-
-}
-std::shared_ptr<LOTModel>
-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<LOTModel> value)
+void LottieFileCache::add(std::string &key, std::shared_ptr<LOTModel> 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<char *>(buf.str().data()));
- mModel = parser.model();
- fileCache.add(path, mModel);
+ LottieParser parser(const_cast<char *>(buf.str().data()));
+ mModel = parser.model();
+ fileCache.add(path, mModel);
- f.close();
- }
+ f.close();
+ }
- return true;
+ return true;
}
std::shared_ptr<LOTModel> LottieLoader::model()
{
- return mModel;
+ return mModel;
}
-
#include "lottiemodel.h"
-#include<stack>
-#include<cassert>
+#include <cassert>
+#include <stack>
-
-
-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 *) {}
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<LOTRepeaterData *>(child.get());
- std::shared_ptr<LOTShapeGroupData> sharedShapeGroup= std::make_shared<LOTShapeGroupData>();
+ LOTRepeaterData *repeater =
+ static_cast<LOTRepeaterData *>(child.get());
+ std::shared_ptr<LOTShapeGroupData> sharedShapeGroup =
+ std::make_shared<LOTShapeGroupData>();
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);
}
}
}
+
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<LOTPath *>(child.get()));
+ updatePathObject(static_cast<LOTPath *>(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<std::shared_ptr<LOTData>> 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<LOTPath *>(child.get()));
+ // put it in the list
+ updatePathObject(static_cast<LOTPath *>(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<std::shared_ptr<LOTData>> mPaintOperationList;
};
accept(&visitor);
}
-
VMatrix LOTTransformData::matrix(int frameNo) const
{
if (mStaticMatrix)
float LOTTransformData::opacity(int frameNo) const
{
- return mOpacity.value(frameNo)/100.f;
+ return mOpacity.value(frameNo) / 100.f;
}
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;
}
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;
}
}
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;
}
}
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;
bool init = false;
if (!grad) {
if (mGradientType == 1)
- grad = std::make_unique<VLinearGradient>(0,0,0,0);
+ grad = std::make_unique<VLinearGradient>(0, 0, 0, 0);
else
- grad = std::make_unique<VRadialGradient>(0,0,0,0,0,0);
+ grad = std::make_unique<VRadialGradient>(0, 0, 0, 0, 0, 0);
grad->mSpread = VGradient::Spread::Pad;
init = true;
}
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;
}
}
-
-
// 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 <iostream>
#include "lottiemodel.h"
-#include"velapsedtimer.h"
-
+#include "rapidjson/document.h"
+#include "velapsedtimer.h"
RAPIDJSON_DIAG_PUSH
#ifdef __GNUC__
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:
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<LOTCompositionData> composition() const {return mComposition;}
- void parseComposition();
- void parseAssets(LOTCompositionData *comp);
- std::shared_ptr<LOTAsset> parseAsset();
- void parseLayers(LOTCompositionData *comp);
- std::shared_ptr<LOTData> parseLayer();
- void parseMaskProperty(LOTLayerData *layer);
- void parseShapesAttr(LOTLayerData *layer);
- void parseObject(LOTGroupData *parent);
- std::shared_ptr<LOTMaskData> parseMaskObject();
- std::shared_ptr<LOTData> parseObjectTypeAttr();
- std::shared_ptr<LOTData> parseGroupObject();
- std::shared_ptr<LOTData> parseRectObject();
- std::shared_ptr<LOTData> parseEllipseObject();
- std::shared_ptr<LOTData> parseShapeObject();
- std::shared_ptr<LOTData> parsePolystarObject();
+ MatteType getMatteType();
+ LayerType getLayerType();
+
+ std::shared_ptr<LOTCompositionData> composition() const
+ {
+ return mComposition;
+ }
+ void parseComposition();
+ void parseAssets(LOTCompositionData *comp);
+ std::shared_ptr<LOTAsset> parseAsset();
+ void parseLayers(LOTCompositionData *comp);
+ std::shared_ptr<LOTData> parseLayer();
+ void parseMaskProperty(LOTLayerData *layer);
+ void parseShapesAttr(LOTLayerData *layer);
+ void parseObject(LOTGroupData *parent);
+ std::shared_ptr<LOTMaskData> parseMaskObject();
+ std::shared_ptr<LOTData> parseObjectTypeAttr();
+ std::shared_ptr<LOTData> parseGroupObject();
+ std::shared_ptr<LOTData> parseRectObject();
+ std::shared_ptr<LOTData> parseEllipseObject();
+ std::shared_ptr<LOTData> parseShapeObject();
+ std::shared_ptr<LOTData> parsePolystarObject();
std::shared_ptr<LOTTransformData> parseTransformObject();
- std::shared_ptr<LOTData> parseFillObject();
- std::shared_ptr<LOTData> parseGFillObject();
- std::shared_ptr<LOTData> parseStrokeObject();
- std::shared_ptr<LOTData> parseGStrokeObject();
- std::shared_ptr<LOTData> parseTrimObject();
- std::shared_ptr<LOTData> parseReapeaterObject();
-
+ std::shared_ptr<LOTData> parseFillObject();
+ std::shared_ptr<LOTData> parseGFillObject();
+ std::shared_ptr<LOTData> parseStrokeObject();
+ std::shared_ptr<LOTData> parseGStrokeObject();
+ std::shared_ptr<LOTData> parseTrimObject();
+ std::shared_ptr<LOTData> 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<typename T>
- bool parseKeyFrameValue(const char* key, LOTKeyFrameValue<T> &value);
- template<typename T>
+ 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 <typename T>
+ bool parseKeyFrameValue(const char *key, LOTKeyFrameValue<T> &value);
+ template <typename T>
void parseKeyFrame(LOTAnimInfo<T> &obj);
- template<typename T>
+ template <typename T>
void parseProperty(LOTAnimatable<T> &obj);
void parseShapeKeyFrame(LOTAnimInfo<LottieShapeData> &obj);
LottieColor toColor(const char *str);
void resolveLayerRefs();
+
protected:
- std::shared_ptr<LOTCompositionData> mComposition;
- LOTCompositionData *compRef;
- LOTLayerData *curLayerRef;
- std::vector<std::shared_ptr<LOTLayerData>> mLayersToUpdate;
- void SkipOut(int depth);
+ std::shared_ptr<LOTCompositionData> mComposition;
+ LOTCompositionData * compRef;
+ LOTLayerData * curLayerRef;
+ std::vector<std::shared_ptr<LOTLayerData>> 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<parseFlags>(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;
}
return true;
}
-bool LottieParserImpl::EnterArray() {
+bool LottieParserImpl::EnterArray()
+{
if (st_ != kEnteringArray) {
- st_ = kError;
+ st_ = kError;
RAPIDJSON_ASSERT(false);
return false;
}
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;
}
* 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;
}
return 0;
}
-bool LottieParserImpl::NextArrayValue() {
+bool LottieParserImpl::NextArrayValue()
+{
if (st_ == kExitingArray) {
ParseNext();
return false;
* 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;
return true;
}
-int LottieParserImpl::GetInt() {
+int LottieParserImpl::GetInt()
+{
if (st_ != kHasNumber || !v_.IsInt()) {
st_ = kError;
RAPIDJSON_ASSERT(false);
return result;
}
-double LottieParserImpl::GetDouble() {
+double LottieParserImpl::GetDouble()
+{
if (st_ != kHasNumber) {
- st_ = kError;
+ st_ = kError;
RAPIDJSON_ASSERT(false);
return 0.;
}
return result;
}
-bool LottieParserImpl::GetBool() {
+bool LottieParserImpl::GetBool()
+{
if (st_ != kHasBool) {
- st_ = kError;
+ st_ = kError;
RAPIDJSON_ASSERT(false);
return false;
}
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_;
}
return 0;
}
-int LottieParserImpl::PeekType() {
+int LottieParserImpl::PeekType()
+{
if (st_ >= kHasNull && st_ <= kHasKey) {
return v_.GetType();
}
}
}
-LottieBlendMode
-LottieParserImpl::getBlendMode()
+LottieBlendMode LottieParserImpl::getBlendMode()
{
RAPIDJSON_ASSERT(PeekType() == kNumberType);
LottieBlendMode mode = LottieBlendMode::Normal;
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());
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<LOTCompositionData> sharedComposition = std::make_shared<LOTCompositionData>();
+ std::shared_ptr<LOTCompositionData> sharedComposition =
+ std::make_shared<LOTCompositionData>();
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());
parseLayers(comp);
} else {
#ifdef DEBUG_PARSER
- vWarning<<"Composition Attribute Skipped : "<<key;
+ vWarning << "Composition Attribute Skipped : " << key;
#endif
Skip(key);
}
composition->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<LOTAsset>
-LottieParserImpl::parseAsset()
+std::shared_ptr<LOTAsset> LottieParserImpl::parseAsset()
{
RAPIDJSON_ASSERT(PeekType() == kObjectType);
std::shared_ptr<LOTAsset> sharedAsset = std::make_shared<LOTAsset>();
- 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()) {
asset->mLayers.push_back(layer);
}
} else {
- #ifdef DEBUG_PARSER
- vWarning<<"Asset Attribute Skipped : "<<key;
- #endif
+#ifdef DEBUG_PARSER
+ vWarning << "Asset Attribute Skipped : " << key;
+#endif
Skip(key);
}
}
}
}
-LottieColor
-LottieParserImpl::toColor(const char *str)
+LottieColor LottieParserImpl::toColor(const char *str)
{
- LottieColor color;
+ LottieColor color;
- RAPIDJSON_ASSERT(strlen(str) == 7);
- RAPIDJSON_ASSERT(str[0] == '#');
+ RAPIDJSON_ASSERT(strlen(str) == 7);
+ RAPIDJSON_ASSERT(str[0] == '#');
- char tmp[3] = { '\0', '\0', '\0' };
- tmp[0] = str[1]; tmp[1] = str[2];
- color.r = std::strtol(tmp, NULL, 16)/ 255.0;
+ char tmp[3] = {'\0', '\0', '\0'};
+ tmp[0] = str[1];
+ tmp[1] = str[2];
+ color.r = std::strtol(tmp, NULL, 16) / 255.0;
- tmp[0] = str[3]; tmp[1] = str[4];
- color.g = std::strtol(tmp, NULL, 16)/ 255.0;
+ tmp[0] = str[3];
+ tmp[1] = str[4];
+ color.g = std::strtol(tmp, NULL, 16) / 255.0;
- tmp[0] = str[5]; tmp[1] = str[6];
- color.b = std::strtol(tmp, NULL, 16)/ 255.0;
+ tmp[0] = str[5];
+ tmp[1] = str[6];
+ color.b = std::strtol(tmp, NULL, 16) / 255.0;
- return color;
+ return color;
}
-MatteType
-LottieParserImpl::getMatteType()
+MatteType LottieParserImpl::getMatteType()
{
RAPIDJSON_ASSERT(PeekType() == kNumberType);
switch (GetInt()) {
* https://github.com/airbnb/lottie-web/blob/master/docs/json/layers/shape.json
*
*/
-std::shared_ptr<LOTData>
-LottieParserImpl::parseLayer()
+std::shared_ptr<LOTData> LottieParserImpl::parseLayer()
{
RAPIDJSON_ASSERT(PeekType() == kObjectType);
- std::shared_ptr<LOTLayerData> sharedLayer = std::make_shared<LOTLayerData>();
+ std::shared_ptr<LOTLayerData> sharedLayer =
+ std::make_shared<LOTLayerData>();
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*/
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")) {
layer->mHasMask = GetBool();
} else if (0 == strcmp(key, "masksProperties")) {
parseMaskProperty(layer);
- }else {
- #ifdef DEBUG_PARSER
- vWarning<<"Layer Attribute Skipped : "<<key;
- #endif
+ } else {
+#ifdef DEBUG_PARSER
+ vWarning << "Layer Attribute Skipped : " << key;
+#endif
Skip(key);
}
}
staticFlag &= mask->isStatic();
}
- layer->setStatic(staticFlag &&
- layer->mTransform->isStatic() &&
+ layer->setStatic(staticFlag && layer->mTransform->isStatic() &&
!hasLayerRef);
return sharedLayer;
}
}
-std::shared_ptr<LOTMaskData>
-LottieParserImpl::parseMaskObject()
+std::shared_ptr<LOTMaskData> LottieParserImpl::parseMaskObject()
{
std::shared_ptr<LOTMaskData> sharedMask = std::make_shared<LOTMaskData>();
- 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")) {
return sharedMask;
}
-
-
void LottieParserImpl::parseShapesAttr(LOTLayerData *layer)
{
RAPIDJSON_ASSERT(PeekType() == kArrayType);
}
}
-std::shared_ptr<LOTData>
-LottieParserImpl::parseObjectTypeAttr()
+std::shared_ptr<LOTData> LottieParserImpl::parseObjectTypeAttr()
{
RAPIDJSON_ASSERT(PeekType() == kStringType);
const char *type = GetString();
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);
}
}
-std::shared_ptr<LOTData>
-LottieParserImpl::parseGroupObject()
+std::shared_ptr<LOTData> LottieParserImpl::parseGroupObject()
{
- std::shared_ptr<LOTShapeGroupData> sharedGroup = std::make_shared<LOTShapeGroupData>();
+ std::shared_ptr<LOTShapeGroupData> sharedGroup =
+ std::make_shared<LOTShapeGroupData>();
LOTShapeGroupData *group = sharedGroup.get();
- while (const char* key = NextObjectKey()) {
+ while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "it")) {
RAPIDJSON_ASSERT(PeekType() == kArrayType);
EnterArray();
RAPIDJSON_ASSERT(PeekType() == kObjectType);
parseObject(group);
}
- group->mTransform = std::dynamic_pointer_cast<LOTTransformData>(group->mChildren.back());
+ group->mTransform = std::dynamic_pointer_cast<LOTTransformData>(
+ group->mChildren.back());
group->mChildren.pop_back();
} else {
Skip(key);
staticFlag &= child.get()->isStatic();
}
- group->setStatic(staticFlag &&
- group->mTransform->isStatic());
+ group->setStatic(staticFlag && group->mTransform->isStatic());
return sharedGroup;
}
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/rect.json
*/
-std::shared_ptr<LOTData>
-LottieParserImpl::parseRectObject()
+std::shared_ptr<LOTData> LottieParserImpl::parseRectObject()
{
std::shared_ptr<LOTRectData> sharedRect = std::make_shared<LOTRectData>();
- 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")) {
Skip(key);
}
}
- obj->setStatic(obj->mPos.isStatic() &&
- obj->mSize.isStatic() &&
+ obj->setStatic(obj->mPos.isStatic() && obj->mSize.isStatic() &&
obj->mRound.isStatic());
return sharedRect;
}
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/ellipse.json
*/
-std::shared_ptr<LOTData>
-LottieParserImpl::parseEllipseObject()
+std::shared_ptr<LOTData> LottieParserImpl::parseEllipseObject()
{
- std::shared_ptr<LOTEllipseData> sharedEllipse = std::make_shared<LOTEllipseData>();
+ std::shared_ptr<LOTEllipseData> sharedEllipse =
+ std::make_shared<LOTEllipseData>();
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")) {
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<LOTData>
-LottieParserImpl::parseShapeObject()
+std::shared_ptr<LOTData> LottieParserImpl::parseShapeObject()
{
- std::shared_ptr<LOTShapeData> sharedShape = std::make_shared<LOTShapeData>();
+ std::shared_ptr<LOTShapeData> sharedShape =
+ std::make_shared<LOTShapeData>();
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 :"<<key;
+ vDebug << "Shape property ignored :" << key;
#endif
Skip(key);
}
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/star.json
*/
-std::shared_ptr<LOTData>
-LottieParserImpl::parsePolystarObject()
+std::shared_ptr<LOTData> LottieParserImpl::parsePolystarObject()
{
- std::shared_ptr<LOTPolystarData> sharedPolystar = std::make_shared<LOTPolystarData>();
+ std::shared_ptr<LOTPolystarData> sharedPolystar =
+ std::make_shared<LOTPolystarData>();
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")) {
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 :"<<key;
+ vDebug << "Polystar property ignored :" << key;
#endif
Skip(key);
}
}
- obj->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()) {
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/trim.json
*/
-std::shared_ptr<LOTData>
-LottieParserImpl::parseTrimObject()
+std::shared_ptr<LOTData> LottieParserImpl::parseTrimObject()
{
std::shared_ptr<LOTTrimData> sharedTrim = std::make_shared<LOTTrimData>();
- 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 :"<<key;
+ vDebug << "Trim property ignored :" << key;
#endif
Skip(key);
}
}
- obj->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<LOTData>
-LottieParserImpl::parseReapeaterObject()
+std::shared_ptr<LOTData> LottieParserImpl::parseReapeaterObject()
{
- std::shared_ptr<LOTRepeaterData> sharedRepeater = std::make_shared<LOTRepeaterData>();
+ std::shared_ptr<LOTRepeaterData> sharedRepeater =
+ std::make_shared<LOTRepeaterData>();
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")) {
obj->mTransform = parseTransformObject();
} else {
#ifdef DEBUG_PARSER
- vDebug<<"Repeater property ignored :"<<key;
+ vDebug << "Repeater property ignored :" << key;
#endif
Skip(key);
}
}
- obj->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<LOTTransformData>
-LottieParserImpl::parseTransformObject()
+std::shared_ptr<LOTTransformData> LottieParserImpl::parseTransformObject()
{
- std::shared_ptr<LOTTransformData> sharedTransform = std::make_shared<LOTTransformData>();
+ std::shared_ptr<LOTTransformData> sharedTransform =
+ std::make_shared<LOTTransformData>();
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")) {
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);
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;
}
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/fill.json
*/
-std::shared_ptr<LOTData>
-LottieParserImpl::parseFillObject()
+std::shared_ptr<LOTData> LottieParserImpl::parseFillObject()
{
std::shared_ptr<LOTFillData> sharedFill = std::make_shared<LOTFillData>();
- 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")) {
obj->mFillRule = getFillRule();
} else {
#ifdef DEBUG_PARSER
- vWarning<<"Fill property skipped = "<<key;
+ vWarning << "Fill property skipped = " << key;
#endif
Skip(key);
}
}
- obj->setStatic(obj->mColor.isStatic() &&
- obj->mOpacity.isStatic());
+ obj->setStatic(obj->mColor.isStatic() && obj->mOpacity.isStatic());
return sharedFill;
}
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/stroke.json
*/
-std::shared_ptr<LOTData>
-LottieParserImpl::parseStrokeObject()
+std::shared_ptr<LOTData> LottieParserImpl::parseStrokeObject()
{
- std::shared_ptr<LOTStrokeData> sharedStroke = std::make_shared<LOTStrokeData>();
+ std::shared_ptr<LOTStrokeData> sharedStroke =
+ std::make_shared<LOTStrokeData>();
LOTStrokeData *obj = sharedStroke.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")) {
parseDashProperty(obj->mDash);
} else {
#ifdef DEBUG_PARSER
- vWarning<<"Stroke property skipped = "<<key;
+ vWarning << "Stroke property skipped = " << key;
#endif
Skip(key);
}
}
- obj->setStatic(obj->mColor.isStatic() &&
- obj->mOpacity.isStatic() &&
- obj->mWidth.isStatic() &&
- obj->mDash.mStatic);
+ obj->setStatic(obj->mColor.isStatic() && obj->mOpacity.isStatic() &&
+ obj->mWidth.isStatic() && obj->mDash.mStatic);
return sharedStroke;
}
-void
-LottieParserImpl::parseGradientProperty(LOTGradient *obj, const char *key)
+void LottieParserImpl::parseGradientProperty(LOTGradient *obj, const char *key)
{
if (0 == strcmp(key, "t")) {
RAPIDJSON_ASSERT(PeekType() == kNumberType);
parseProperty(obj->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 = "<<key;
+ vWarning << "Gradient property skipped = " << key;
#endif
- Skip(key);
+ Skip(key);
}
- obj->setStatic(obj->mOpacity.isStatic() &&
- obj->mStartPoint.isStatic() &&
- obj->mEndPoint.isStatic() &&
- obj->mHighlightAngle.isStatic() &&
- obj->mHighlightLength.isStatic() &&
- obj->mGradient.isStatic());
-
+ obj->setStatic(
+ obj->mOpacity.isStatic() && obj->mStartPoint.isStatic() &&
+ obj->mEndPoint.isStatic() && obj->mHighlightAngle.isStatic() &&
+ obj->mHighlightLength.isStatic() && obj->mGradient.isStatic());
}
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/gfill.json
*/
-std::shared_ptr<LOTData>
-LottieParserImpl::parseGFillObject()
+std::shared_ptr<LOTData> LottieParserImpl::parseGFillObject()
{
- std::shared_ptr<LOTGFillData> sharedGFill = std::make_shared<LOTGFillData>();
+ std::shared_ptr<LOTGFillData> sharedGFill =
+ std::make_shared<LOTGFillData>();
LOTGFillData *obj = sharedGFill.get();
- while (const char* key = NextObjectKey()) {
+ while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "r")) {
obj->mFillRule = getFillRule();
} else {
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 {
}
// 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;
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/gstroke.json
*/
-std::shared_ptr<LOTData>
-LottieParserImpl::parseGStrokeObject()
+std::shared_ptr<LOTData> LottieParserImpl::parseGStrokeObject()
{
- std::shared_ptr<LOTGStrokeData> sharedGStroke = std::make_shared<LOTGStrokeData>();
+ std::shared_ptr<LOTGStrokeData> sharedGStroke =
+ std::make_shared<LOTGStrokeData>();
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")) {
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;
}
void LottieParserImpl::parseArrayValue(LottieColor &color)
{
float val[4];
- int i=0;
+ int i = 0;
while (NextArrayValue()) {
val[i++] = GetDouble();
}
void LottieParserImpl::parseArrayValue(VPointF &pt)
{
float val[4];
- int i=0;
+ int i = 0;
while (NextArrayValue()) {
val[i++] = GetDouble();
}
void LottieParserImpl::getValue(VPointF &pt)
{
float val[4];
- int i=0;
+ int i = 0;
RAPIDJSON_ASSERT(PeekType() == kArrayType);
EnterArray();
while (NextArrayValue()) {
void LottieParserImpl::getValue(LottieColor &color)
{
float val[4];
- int i=0;
+ int i = 0;
RAPIDJSON_ASSERT(PeekType() == kArrayType);
EnterArray();
while (NextArrayValue()) {
void LottieParserImpl::getValue(LottieShapeData &obj)
{
- std::vector<VPointF> inPoint; /* "i" */
- std::vector<VPointF> outPoint; /* "o" */
- std::vector<VPointF> vertices; /* "v" */
- std::vector<VPointF> points;
- bool closed=false;
+ std::vector<VPointF> inPoint; /* "i" */
+ std::vector<VPointF> outPoint; /* "o" */
+ std::vector<VPointF> vertices; /* "v" */
+ std::vector<VPointF> 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")) {
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<VPointF>();
} 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 <size ; i++ ) {
- points.push_back(vertices[i-1] + outPoint[i-1]); // CP1 = start + outTangent
- points.push_back(vertices[i] + inPoint[i]); // CP2 = end + inTangent
- points.push_back(vertices[i]); //end point
+ for (int i = 1; i < size; i++) {
+ points.push_back(vertices[i - 1] +
+ outPoint[i - 1]); // CP1 = start + outTangent
+ points.push_back(vertices[i] +
+ inPoint[i]); // CP2 = end + inTangent
+ points.push_back(vertices[i]); // end point
}
if (closed) {
- points.push_back(vertices[size-1] + outPoint[size-1]); // CP1 = start + outTangent
- points.push_back(vertices[0] + inPoint[0]); // CP2 = end + inTangent
- points.push_back(vertices[0]); //end point
+ points.push_back(vertices[size - 1] +
+ outPoint[size - 1]); // CP1 = start + outTangent
+ points.push_back(vertices[0] +
+ inPoint[0]); // CP2 = end + inTangent
+ points.push_back(vertices[0]); // end point
}
}
obj.mPoints = std::move(points);
obj.mClosed = closed;
}
-VPointF
-LottieParserImpl::parseInperpolatorPoint()
+VPointF LottieParserImpl::parseInperpolatorPoint()
{
VPointF cp;
RAPIDJSON_ASSERT(PeekType() == kObjectType);
EnterObject();
- while(const char* key = NextObjectKey()) {
+ while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "x")) {
if (PeekType() == kNumberType) {
cp.setX(GetDouble());
return cp;
}
-template<typename T>
-bool LottieParserImpl::parseKeyFrameValue(const char* key, LOTKeyFrameValue<T> &value)
+template <typename T>
+bool LottieParserImpl::parseKeyFrameValue(const char * key,
+ LOTKeyFrameValue<T> &value)
{
if (0 == strcmp(key, "s")) {
getValue(value.mStartValue);
return true;
}
-template<>
-bool LottieParserImpl::parseKeyFrameValue(const char* key, LOTKeyFrameValue<VPointF> &value)
+template <>
+bool LottieParserImpl::parseKeyFrameValue(const char * key,
+ LOTKeyFrameValue<VPointF> &value)
{
if (0 == strcmp(key, "s")) {
getValue(value.mStartValue);
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/properties/multiDimensionalKeyframed.json
*/
-template<typename T>
+template <typename T>
void LottieParserImpl::parseKeyFrame(LOTAnimInfo<T> &obj)
{
EnterObject();
LOTKeyFrame<T> 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 = "<<key;
+ vDebug << "key frame property skipped = " << key;
#endif
- 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>(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>(
+ 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
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/properties/shape.json
*/
-void
-LottieParserImpl::parseShapeProperty(LOTAnimatable<LottieShapeData> &obj)
+void LottieParserImpl::parseShapeProperty(LOTAnimatable<LottieShapeData> &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<LOTAnimInfo<LottieShapeData>>();
+ obj.mAnimInfo =
+ std::make_unique<LOTAnimInfo<LottieShapeData>>();
parseKeyFrame(*obj.mAnimInfo.get());
}
} else {
}
} else {
#ifdef DEBUG_PARSER
- vDebug<<"shape property ignored = "<<key;
+ vDebug << "shape property ignored = " << key;
#endif
Skip(nullptr);
}
/*
* https://github.com/airbnb/lottie-web/tree/master/docs/json/properties
*/
-template<typename T>
+template <typename T>
void LottieParserImpl::parseProperty(LOTAnimatable<T> &obj)
{
EnterObject();
- while (const char* key = NextObjectKey()) {
+ while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "k")) {
if (PeekType() == kNumberType) {
/*single value property with no animation*/
}
}
}
- } else if (0 == strcmp(key, "ix")){
+ } else if (0 == strcmp(key, "ix")) {
RAPIDJSON_ASSERT(PeekType() == kNumberType);
obj.mPropertyIndex = GetInt();
} else {
}
}
-class LOTDataInspector : public LOTDataVisitor
-{
+class LOTDataInspector : public LOTDataVisitor {
public:
- 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);
+ 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<LOTLayerData *>(obj);
- vDebug<<"[LAYER_END:: type:"<<layerType(layer->mLayerType).c_str()<<" id:"<<layer->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";
delete d;
}
-LottieParser::LottieParser(char* str): d(new LottieParserImpl(str))
+LottieParser::LottieParser(char *str) : d(new LottieParserImpl(str))
{
d->parseComposition();
}
std::shared_ptr<LOTModel> LottieParser::model()
{
- std::shared_ptr<LOTModel> model= std::make_shared<LOTModel>();
- model->mRoot = d->composition();
- model->mRoot->processPathOperatorObjects();
- model->mRoot->processRepeaterObjects();
+ std::shared_ptr<LOTModel> model = std::make_shared<LOTModel>();
+ 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
#include <lottieplayer.h>
-#include "lottiemodel.h"
-#include "lottieloader.h"
#include "lottieitem.h"
+#include "lottieloader.h"
+#include "lottiemodel.h"
-#include<fstream>
-
+#include <fstream>
-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<LOTNode *>& 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<LOTNode *> &renderList() const;
+ bool render(float pos, const LOTBuffer &buffer);
+
public:
- std::string mFilePath;
- std::shared_ptr<LOTModel> mModel;
- std::unique_ptr<LOTCompItem> mCompItem;
- VSize mSize;
- std::atomic<bool> mRenderInProgress;
+ std::string mFilePath;
+ std::shared_ptr<LOTModel> mModel;
+ std::unique_ptr<LOTCompItem> mCompItem;
+ VSize mSize;
+ std::atomic<bool> mRenderInProgress;
+
private:
- float mPos;
+ float mPos;
};
void LOTPlayerPrivate::setSize(const VSize &sz)
h = size.height();
}
-const std::vector<LOTNode *>& LOTPlayerPrivate::renderList() const
+const std::vector<LOTNode *> &LOTPlayerPrivate::renderList() const
{
if (!mCompItem.get()) {
- //FIXME: Reference is not good...
+ // FIXME: Reference is not good...
}
return mCompItem->renderList();
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);
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<LOTCompItem>(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<LOTCompItem>(mModel.get());
+ setPos(0);
+ return true;
+ }
+ return false;
}
/*
* 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<bool> sender;
- std::future<bool> receiver;
- LOTPlayerPrivate *playerImpl;
- float pos;
- LOTBuffer buffer;
+struct RenderTask {
+ RenderTask() { receiver = sender.get_future(); }
+ std::promise<bool> sender;
+ std::future<bool> receiver;
+ LOTPlayerPrivate * playerImpl;
+ float pos;
+ LOTBuffer buffer;
};
-#include<vtaskqueue.h>
+#include <vtaskqueue.h>
class RenderTaskScheduler {
- const unsigned _count{std::thread::hardware_concurrency()};
+ const unsigned _count{std::thread::hardware_concurrency()};
std::vector<std::thread> _threads;
std::vector<TaskQueue<RenderTask>> _q{_count};
- std::atomic<unsigned> _index{0};
+ std::atomic<unsigned> _index{0};
- void run(unsigned i) {
+ void run(unsigned i)
+ {
while (true) {
RenderTask *task = nullptr;
}
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<bool> async(RenderTask *task) {
+ std::future<bool> async(RenderTask *task)
+ {
auto receiver = std::move(task->receiver);
auto i = _index++;
return receiver;
}
- std::future<bool> render(LOTPlayerPrivate *impl,
- float pos, LOTBuffer &buffer) {
+ std::future<bool> render(LOTPlayerPrivate *impl, float pos,
+ LOTBuffer &buffer)
+ {
RenderTask *task = new RenderTask();
task->playerImpl = impl;
task->pos = pos;
};
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
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<LOTNode *>& LOTPlayer::renderList()const
+const std::vector<LOTNode *> &LOTPlayer::renderList() const
{
return d->renderList();
}
return d->render(pos, buffer);
}
-LOTNode::~LOTNode()
-{
-}
-
-LOTNode::LOTNode()
-{
-}
-
-
+LOTNode::~LOTNode() {}
+LOTNode::LOTNode() {}
/* */
/***************************************************************************/
-#include <math.h>
#include "v_ft_math.h"
+#include <math.h>
+#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 */
/* */
/*************************************************************************/
- /* 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 */
-
/* */
/***************************************************************************/
- /*************************************************************************/
- /* */
- /* 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 <limits.h>
+#include <setjmp.h>
#include <stddef.h>
#include <string.h>
-#include <setjmp.h>
-#include <limits.h>
-#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_
#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;
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: */
/* 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;
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. */
- /* */
- /*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* SW_FT_Outline_Decompose */
- /* */
- /* <Description> */
- /* 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. */
- /* */
- /* <Input> */
- /* outline :: A pointer to the source target. */
- /* */
- /* func_interface :: A table of `emitters', i.e., function pointers */
- /* called during decomposition to indicate path */
- /* operations. */
- /* */
- /* <InOut> */
- /* user :: A typeless pointer which is passed to each */
- /* emitter during the decomposition. It can be */
- /* used to store the state during the */
- /* decomposition. */
- /* */
- /* <Return> */
- /* 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. */
+/* */
+/*************************************************************************/
+
+/*************************************************************************/
+/* */
+/* <Function> */
+/* SW_FT_Outline_Decompose */
+/* */
+/* <Description> */
+/* 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. */
+/* */
+/* <Input> */
+/* outline :: A pointer to the source target. */
+/* */
+/* func_interface :: A table of `emitters', i.e., function pointers */
+/* called during decomposition to indicate path */
+/* operations. */
+/* */
+/* <InOut> */
+/* user :: A typeless pointer which is passed to each */
+/* emitter during the decomposition. It can be */
+/* used to store the state during the */
+/* decomposition. */
+/* */
+/* <Return> */
+/* 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 */
/* */
/***************************************************************************/
-
-#include "v_ft_math.h"
#include "v_ft_stroker.h"
#include <assert.h>
-#include <string.h>
#include <stdlib.h>
+#include <string.h>
+#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;
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 */
/* 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;
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 */
#include "vbezier.h"
-#include<cmath>
+#include <cmath>
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,
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;
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;
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;
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
-
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;
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);
}
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);
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
#include "vbitmap.h"
+#include <string.h>
#include "vglobal.h"
-#include<string.h>
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;
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;
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;
void VBitmap::detach()
{
if (d) {
- if (d->ref.isShared() || d->roData)
- *this = copy();
+ if (d->ref.isShared() || d->roData) *this = copy();
}
}
{
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;
}
{
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;
}
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;
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());
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.
y = 0;
}
}
- //TODO implement properly.
+ // TODO implement properly.
return image;
-
}
int VBitmap::stride() 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;
}
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
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);
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
-#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)
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();
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;
}
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();
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;
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;
#ifndef VBRUSH_H
#define VBRUSH_H
-#include"vglobal.h"
-#include"vpoint.h"
-#include"vmatrix.h"
-#include<vector>
+#include <vector>
+#include "vglobal.h"
+#include "vmatrix.h"
+#include "vpoint.h"
V_BEGIN_NAMESPACE
-typedef std::pair<float, VColor> VGradientStop;
+typedef std::pair<float, VColor> VGradientStop;
typedef std::vector<VGradientStop> 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;
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
-#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);
+ }
}
/*
= 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);
}
}
}
/* 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;
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 {
}
}
-
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() {}
#ifndef VCOWPTR_H
#define VCOWPTR_H
-#include<assert.h>
+#include <assert.h>
+#include "vglobal.h"
template <typename T>
class vcow_ptr {
model() = default;
template <class... Args>
- explicit model(Args&&... args) : mValue(std::forward<Args>(args)...) {}
+ explicit model(Args&&... args) : mValue(std::forward<Args>(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 <class... Args>
- vcow_ptr(Args&&... args)
- : mModel(new model(std::forward<Args>(args)...)) {}
+ vcow_ptr(Args&&... args) : mModel(new model(std::forward<Args>(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;
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
-#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;
// 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<const VDasher::Dash *>(dashArray);
- mArraySize = size/2;
- mDashOffset = dashArray[size-1];
+ mArraySize = size / 2;
+ mDashOffset = dashArray[size - 1];
mCurrentDashIndex = 0;
mCurrentDashLength = 0;
mIsCurrentOperationGap = false;
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
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;
}
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<VPath::Element> &elms = path.elements();
- const std::vector<VPointF> &pts = path.points();
- const VPointF *ptPtr = pts.data();
+ const std::vector<VPointF> & 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;
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
#include "vdebug.h"
-#include <cstring>
+#include <atomic>
#include <chrono>
+#include <cstring>
#include <ctime>
+#include <fstream>
+#include <queue>
+#include <sstream>
#include <thread>
#include <tuple>
-#include <atomic>
-#include <queue>
-#include <fstream>
-#include<sstream>
-namespace
-{
+namespace {
- /* Returns microseconds since epoch */
- uint64_t timestamp_now()
- {
- return std::chrono::duration_cast<std::chrono::microseconds>(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::microseconds>(
+ 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 <typename T, typename Tuple>
+struct TupleIndex;
- template < typename T,typename ... Types >
- struct TupleIndex < T, std::tuple < T, Types... > >
- {
+template <typename T, typename... Types>
+struct TupleIndex<T, std::tuple<T, Types...> > {
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 <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;
+};
-} // 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<char, uint32_t, uint64_t, int32_t, int64_t, double,
+ VDebug::string_literal_t, char*>
+ 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:
return "CRIT";
}
return "XXXX";
- }
+}
- template < typename Arg >
- void VDebug::encode(Arg arg)
- {
+template <typename Arg>
+void VDebug::encode(Arg arg)
+{
*reinterpret_cast<Arg*>(buffer()) = arg;
m_bytes_used += sizeof(Arg);
- }
+}
- template < typename Arg >
- void VDebug::encode(Arg arg, uint8_t type_id)
- {
+template <typename Arg>
+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<uint8_t>(type_id);
+ encode<Arg>(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<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);
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<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);
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 <typename Arg>
+char* decode(std::ostream& os, char* b, Arg* dummy)
+{
+ Arg arg = *reinterpret_cast<Arg*>(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<VDebug::string_literal_t*>(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<int>(*start);
+ start++;
- switch (type_id)
- {
+ switch (type_id) {
case 0:
- stringify(os, decode(os, start, static_cast<std::tuple_element<0, SupportedTypes>::type*>(nullptr)), end);
+ stringify(
+ os,
+ decode(os, start,
+ static_cast<std::tuple_element<0, SupportedTypes>::type*>(
+ nullptr)),
+ end);
return;
case 1:
- stringify(os, decode(os, start, static_cast<std::tuple_element<1, SupportedTypes>::type*>(nullptr)), end);
+ stringify(
+ os,
+ decode(os, start,
+ static_cast<std::tuple_element<1, SupportedTypes>::type*>(
+ nullptr)),
+ end);
return;
case 2:
- stringify(os, decode(os, start, static_cast<std::tuple_element<2, SupportedTypes>::type*>(nullptr)), end);
+ stringify(
+ os,
+ decode(os, start,
+ static_cast<std::tuple_element<2, SupportedTypes>::type*>(
+ nullptr)),
+ end);
return;
case 3:
- stringify(os, decode(os, start, static_cast<std::tuple_element<3, SupportedTypes>::type*>(nullptr)), end);
+ stringify(
+ os,
+ decode(os, start,
+ static_cast<std::tuple_element<3, SupportedTypes>::type*>(
+ nullptr)),
+ end);
return;
case 4:
- stringify(os, decode(os, start, static_cast<std::tuple_element<4, SupportedTypes>::type*>(nullptr)), end);
+ stringify(
+ os,
+ decode(os, start,
+ static_cast<std::tuple_element<4, SupportedTypes>::type*>(
+ nullptr)),
+ end);
return;
case 5:
- stringify(os, decode(os, start, static_cast<std::tuple_element<5, SupportedTypes>::type*>(nullptr)), end);
+ stringify(
+ os,
+ decode(os, start,
+ static_cast<std::tuple_element<5, SupportedTypes>::type*>(
+ nullptr)),
+ end);
return;
case 6:
- stringify(os, decode(os, start, static_cast<std::tuple_element<6, SupportedTypes>::type*>(nullptr)), end);
+ stringify(
+ os,
+ decode(os, start,
+ static_cast<std::tuple_element<6, SupportedTypes>::type*>(
+ nullptr)),
+ end);
return;
case 7:
- stringify(os, decode(os, start, static_cast<std::tuple_element<7, SupportedTypes>::type*>(nullptr)), end);
+ stringify(
+ os,
+ decode(os, start,
+ static_cast<std::tuple_element<7, SupportedTypes>::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<size_t>(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<size_t>(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<size_t>(2 * m_buffer_size), required_size);
+ std::unique_ptr<char[]> 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<char*, SupportedTypes>::value;
*reinterpret_cast<uint8_t*>(b++) = static_cast<uint8_t>(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<string_literal_t>(
+ arg, TupleIndex<string_literal_t, SupportedTypes>::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<int32_t>(arg, TupleIndex<int32_t, SupportedTypes>::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<uint32_t>(arg, TupleIndex<uint32_t, SupportedTypes>::value);
return *this;
- }
+}
// VDebug& VDebug::operator<<(int64_t arg)
// {
// 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<uint64_t>(arg, TupleIndex<uint64_t, SupportedTypes>::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<int64_t>(arg, TupleIndex<int64_t, SupportedTypes>::value);
+ return *this;
+}
- VDebug& VDebug::operator<<(double arg)
- {
- encode < double >(arg, TupleIndex < double, SupportedTypes >::value);
+VDebug& VDebug::operator<<(double arg)
+{
+ encode<double>(arg, TupleIndex<double, SupportedTypes>::value);
return *this;
- }
+}
- VDebug& VDebug::operator<<(char arg)
- {
- encode < char >(arg, TupleIndex < char, SupportedTypes >::value);
+VDebug& VDebug::operator<<(char arg)
+{
+ encode<char>(arg, TupleIndex<char, SupportedTypes>::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<Item*>(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<Item*>(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<unsigned int> 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<Item*>(std::malloc(size * sizeof(Item))))
- {
- for (size_t i = 0; i <= size; ++i)
- {
+ Buffer() : m_buffer(static_cast<Item*>(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<unsigned int> 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<Buffer> 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<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;
+};
- 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;
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<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)
{
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);
}
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<State> m_state;
+ std::unique_ptr<BufferBase> 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> nanologger;
+std::atomic<NanoLogger*> 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<unsigned int> loglevel = {0};
- void set_log_level(LogLevel level)
- {
+void set_log_level(LogLevel level)
+{
loglevel.store(static_cast<unsigned int>(level), std::memory_order_release);
- }
+}
- bool is_logged(LogLevel level)
- {
- return static_cast<unsigned int>(level) >= loglevel.load(std::memory_order_relaxed);
- }
+bool is_logged(LogLevel level)
+{
+ return static_cast<unsigned int>(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)
#ifndef VDEBUG_H
#define VDEBUG_H
#include <cstdint>
+#include <iosfwd>
#include <memory>
#include <string>
-#include <iosfwd>
#include <type_traits>
-
-
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 <size_t N>
+ 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 Arg>
+ typename std::enable_if<std::is_same<Arg, char const*>::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 Arg>
+ typename std::enable_if<std::is_same<Arg, char*>::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 <typename Arg>
void encode(Arg arg);
- template < typename Arg >
+ template <typename Arg>
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<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 */];
};
-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.
* 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 {
};
/*
* 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
#include "vdrawable.h"
-#include"vdasher.h"
-#include"vraster.h"
+#include "vdasher.h"
+#include "vraster.h"
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);
}
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;
#ifndef VDRAWABLE_H
#define VDRAWABLE_H
+#include <future>
#include "vbrush.h"
#include "vpath.h"
#include "vrle.h"
-#include<future>
-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,
typedef vFlag<DirtyState> 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<VRle> 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<VRle> 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
-#include"vdrawhelper.h"
-#include<cstring>
-#include<climits>
-#include<unordered_map>
-#include<mutex>
+#include "vdrawhelper.h"
+#include <climits>
+#include <cstring>
+#include <mutex>
+#include <unordered_map>
-
-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<uint64_t, std::shared_ptr<const CacheInfo>> VGradientColorTableHash;
+ typedef std::unordered_multimap<uint64_t, std::shared_ptr<const CacheInfo>>
+ VGradientColorTableHash;
bool generateGradientColorTable(const VGradientStops &stops,
uint32_t *colorTable, int size);
- inline const std::shared_ptr<const CacheInfo> getBuffer(const VGradient &gradient)
+ inline const std::shared_ptr<const CacheInfo> getBuffer(
+ const VGradient &gradient)
{
- uint64_t hash_val = 0;
+ uint64_t hash_val = 0;
std::shared_ptr<const CacheInfo> info;
const VGradientStops &stops = gradient.mStops;
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
}
if (!info) {
// didn't find an exact match
- info = addCacheElement(hash_val, gradient);
+ info = addCacheElement(hash_val, gradient);
}
}
cacheAccess.unlock();
}
protected:
- inline uint maxCacheSize() const { return 60; }
- const std::shared_ptr<const CacheInfo> addCacheElement(uint64_t hash_val, const VGradient &gradient)
+ inline uint maxCacheSize() const { return 60; }
+ const std::shared_ptr<const CacheInfo> addCacheElement(
+ uint64_t hash_val, const VGradient &gradient)
{
if (cache.size() == maxCacheSize()) {
int count = rand() % maxCacheSize();
}
}
auto cache_entry = std::make_shared<CacheInfo>(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;
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()
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
*/
#define FIXPT_BITS 8
-#define FIXPT_SIZE (1<<FIXPT_BITS)
-static inline void
-getLinearGradientValues(LinearGradientValues *v, const VSpanData *data)
+#define FIXPT_SIZE (1 << FIXPT_BITS)
+static inline void getLinearGradientValues(LinearGradientValues *v,
+ const VSpanData * data)
{
const VGradientData *grad = &data->mGradient;
v->dx = grad->linear.x2 - grad->linear.x1;
}
}
-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;
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;
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);
} 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;
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) {
}
}
-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)) {
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;
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;
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) {
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) {
}
}
-
-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;
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);
}
}
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);
}
}
-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:
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:
}
#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
#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)
-
#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<cstring>
+#include <cstring>
+#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<mHeight); return mBuffer + y * mBytesPerLine; }
+ inline uchar *scanLine(int y)
+ {
+ assert(y >= 0);
+ assert(y < mHeight);
+ return mBuffer + y * mBytesPerLine;
+ }
int width() const { return mWidth; }
int height() const { return mHeight; }
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 {
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<VSpanData::Pinnable> 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
#if defined(__SSE2__)
-#include"vdrawhelper.h"
+#include "vdrawhelper.h"
-#include <xmmintrin.h> /* for _mm_shuffle_pi16 and _MM_SHUFFLE */
#include <emmintrin.h> /* for SSE2 intrinsics */
+#include <xmmintrin.h> /* 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
-#include"velapsedtimer.h"
+#include "velapsedtimer.h"
void VElapsedTimer::start()
{
double VElapsedTimer::elapsed() const
{
if (!isValid()) return 0;
- return std::chrono::duration<double, std::milli>(std::chrono::high_resolution_clock::now()-clock).count();
+ return std::chrono::duration<double, std::milli>(
+ 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;
}
-
#ifndef VELAPSEDTIMER_H
#define VELAPSEDTIMER_H
+#include <chrono>
#include "vglobal.h"
-#include<chrono>
-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
#ifndef VGLOBAL_H
#define VGLOBAL_H
-#include<iostream>
#include <cmath>
-#include<cstdint>
-#include<type_traits>
-#include<utility>
-
-typedef uint32_t uint;
-typedef uint16_t ushort;
-typedef uint8_t uchar;
+#include <cstdint>
+#include <iostream>
+#include <type_traits>
+#include <utility>
+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<atomic>
-class RefCount
-{
+#include <atomic>
+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;
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<int> atomic;
};
template <typename T>
-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 <typename T>
-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)
{
// 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; }
constexpr inline operator uint() const noexcept { return uint(i); }
};
-template<typename Enum>
-class vFlag
-{
+template <typename Enum>
+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<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<Enum>::value),
+ "vFlag is only usable on enumeration types.");
typedef typename std::conditional<
- std::is_unsigned<typename std::underlying_type<Enum>::type>::value,
- unsigned int,
- signed int
- >::type Int;
+ std::is_unsigned<typename std::underlying_type<Enum>::type>::value,
+ unsigned int, signed int>::type Int;
typedef Enum enum_type;
// compiler-generated copy/move ctor/assignment operators are fine!
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);
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;
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
-#include"vinterpolator.h"
-#include<cmath>
+#include "vinterpolator.h"
+#include <cmath>
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
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
-#include"vmatrix.h"
-#include<cmath>
-#include<cstring>
-#include<cassert>
-#include<vglobal.h>
+#include "vmatrix.h"
+#include <vglobal.h>
+#include <cassert>
+#include <cmath>
+#include <cstring>
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
VMatrix &VMatrix::operator*=(float num)
{
- if (num == 1.)
- return *this;
+ if (num == 1.) return *this;
m11 *= num;
m12 *= 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:
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;
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;
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;
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;
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) {
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;
}
}
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;
}
}
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;
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:
// 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
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
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;
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);
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);
float x = 0, y = 0;
VMatrix::MatrixType t = type();
- switch(t) {
+ switch (t) {
case MatrixType::None:
x = fx;
y = fy;
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;
}
}
static std::string type_helper(VMatrix::MatrixType t)
{
- switch(t) {
+ switch (t) {
case VMatrix::MatrixType::None:
return "MatrixType::None";
break;
}
return "";
}
-std::ostream& operator<<(std::ostream& os, const VMatrix& o)
+std::ostream &operator<<(std::ostream &os, const VMatrix &o)
{
- os<<"[Matrix: "<<"type ="<<type_helper(o.type())<<", Data : "<<o.m11<<" "<<o.m12<<" "<<o.m13<<" "<<o.m21<<" "<<o.m22<<" "<<o.m23<<" "<<o.mtx<<" "<<o.mty<<" "<<o.m33<<" "<<"]"<<std::endl;
+ os << "[Matrix: "
+ << "type =" << type_helper(o.type()) << ", Data : " << o.m11 << " "
+ << o.m12 << " " << o.m13 << " " << o.m21 << " " << o.m22 << " " << o.m23
+ << " " << o.mtx << " " << o.mty << " " << o.m33 << " "
+ << "]" << std::endl;
return os;
}
V_END_NAMESPACE
-
#ifndef VMATRIX_H
#define VMATRIX_H
-#include"vpoint.h"
-#include "vregion.h"
#include "vglobal.h"
+#include "vpoint.h"
+#include "vregion.h"
V_BEGIN_NAMESPACE
struct VMatrixData;
-class VMatrix
-{
+class VMatrix {
public:
- enum class Axis {
- X,
- Y,
- Z
- };
+ enum class Axis { X, Y, Z };
enum class MatrixType {
- None = 0x00,
+ None = 0x00,
Translate = 0x01,
- Scale = 0x02,
- Rotate = 0x04,
- Shear = 0x08,
- Project = 0x10
+ Scale = 0x02,
+ Rotate = 0x04,
+ Shear = 0x08,
+ Project = 0x10
};
- bool isAffine() const;
- bool isIdentity() const;
- bool isInvertible() const;
- bool isScaling() const;
- bool isRotating() const;
- bool isTranslating() const;
- MatrixType type() const;
+ bool isAffine() const;
+ bool isIdentity() const;
+ bool isInvertible() const;
+ bool isScaling() const;
+ bool isRotating() const;
+ bool isTranslating() const;
+ MatrixType type() const;
inline float determinant() const;
- VMatrix &translate(VPointF pos) { return translate(pos.x(), pos.y());};
+ VMatrix &translate(VPointF pos) { return translate(pos.x(), pos.y()); };
VMatrix &translate(float dx, float dy);
- VMatrix &scale(VPointF s){ return scale(s.x(), s.y());};
+ VMatrix &scale(VPointF s) { return scale(s.x(), s.y()); };
VMatrix &scale(float sx, float sy);
VMatrix &shear(float sh, float sv);
VMatrix &rotate(float a, Axis axis = VMatrix::Axis::Z);
VMatrix &rotateRadians(float a, Axis axis = VMatrix::Axis::Z);
- VPointF map(const VPointF &p) const;
+ VPointF map(const VPointF &p) const;
inline VPointF map(float x, float y) const;
- VRect map(const VRect &r) const;
- VRegion map(const VRegion &r) const;
+ VRect map(const VRect &r) const;
+ VRegion map(const VRegion &r) const;
V_REQUIRED_RESULT VMatrix inverted(bool *invertible = nullptr) const;
V_REQUIRED_RESULT VMatrix adjoint() const;
- VMatrix operator*(const VMatrix &o) const;
- VMatrix &operator*=(const VMatrix &);
- VMatrix &operator*=(float mul);
- VMatrix &operator/=(float div);
- bool operator==(const VMatrix &) const;
- bool operator!=(const VMatrix &) const;
- bool fuzzyCompare(const VMatrix &) const;
- friend std::ostream& operator<<(std::ostream& os, const VMatrix& o);
+ VMatrix operator*(const VMatrix &o) const;
+ VMatrix & operator*=(const VMatrix &);
+ VMatrix & operator*=(float mul);
+ VMatrix & operator/=(float div);
+ bool operator==(const VMatrix &) const;
+ bool operator!=(const VMatrix &) const;
+ bool fuzzyCompare(const VMatrix &) const;
+ friend std::ostream &operator<<(std::ostream &os, const VMatrix &o);
+
private:
friend struct VSpanData;
mutable MatrixType mType{MatrixType::None};
mutable MatrixType dirty{MatrixType::None};
- float m11{1}, m12{0}, m13{0};
- float m21{0}, m22{1}, m23{0};
- float mtx{0}, mty{0}, m33{1};
+ float m11{1}, m12{0}, m13{0};
+ float m21{0}, m22{1}, m23{0};
+ float mtx{0}, mty{0}, m33{1};
};
inline VPointF VMatrix::map(float x, float y) const
V_END_NAMESPACE
-#endif // VMATRIX_H
+#endif // VMATRIX_H
-#include"vpainter.h"
-#include"vdrawhelper.h"
+#include "vpainter.h"
+#include "vdrawhelper.h"
V_BEGIN_NAMESPACE
-class VPainterImpl
-{
+class VPainterImpl {
public:
void drawRle(const VPoint &pos, const VRle &rle);
+
public:
VRasterBuffer mBuffer;
VSpanData mSpanData;
void VPainterImpl::drawRle(const VPoint &pos, const VRle &rle)
{
if (rle.isEmpty()) return;
- //mSpanData.updateSpanFunc();
+ // mSpanData.updateSpanFunc();
if (!mSpanData.mUnclippedBlendFunc) return;
// do draw after applying clip.
- rle.intersect(mSpanData.mSystemClip, mSpanData.mUnclippedBlendFunc, &mSpanData);
+ rle.intersect(mSpanData.mSystemClip, mSpanData.mUnclippedBlendFunc,
+ &mSpanData);
}
VPainter::~VPainter()
{
mImpl->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)
{
#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
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
-#include"vpath.h"
-#include<vector>
-#include<cassert>
-#include"vdebug.h"
-#include"vbezier.h"
+#include "vpath.h"
+#include <cassert>
+#include <vector>
+#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;
}
}
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);
const VPointF &lastPt = m_points.back();
if (!fuzzyCompare(mStartPoint, lastPt)) {
- lineTo(mStartPoint);
+ lineTo(mStartPoint);
}
m_elements.push_back(VPath::Element::Close);
mNewSegment = true;
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<point_count; i+=3) {
- cubicTo(pts[i], pts[i+1], pts[i+2]);
+ for (int i = 0; i < point_count; i += 3) {
+ cubicTo(pts[i], pts[i + 1], pts[i + 2]);
}
}
-void VPath::VPathData::addCircle(float cx, float cy, float radius, VPath::Direction dir)
+void VPath::VPathData::addCircle(float cx, float cy, float radius,
+ VPath::Direction dir)
{
- addOval(VRectF(cx-radius, cy-radius, 2*radius, 2*radius) , dir);
+ addOval(VRectF(cx - radius, cy - radius, 2 * radius, 2 * radius), dir);
}
void VPath::VPathData::addOval(const VRectF &rect, VPath::Direction dir)
float h2 = rect.height() / 2;
float h2k = h2 * PATH_KAPPA;
-
if (dir == VPath::Direction::CW) {
- // 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));
+ // 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));
}
}
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);
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;
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();
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];
}
}
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))
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
#ifndef VPATH_H
#define VPATH_H
+#include <vector>
+#include "vcowptr.h"
+#include "vmatrix.h"
#include "vpoint.h"
#include "vrect.h"
-#include "vmatrix.h"
-#include<vector>
-#include<vcowptr.h>
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<VPath::Element> &elements() const;
- const std::vector<VPointF> &points() const;
+ const std::vector<VPointF> & 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<VPath::Element> &elements() const { return m_elements;}
- const std::vector<VPointF> &points() const {return m_points;}
- std::vector<VPointF> m_points;
- std::vector<VPath::Element> 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<VPath::Element> &elements() const
+ {
+ return m_elements;
+ }
+ const std::vector<VPointF> &points() const { return m_points; }
+ std::vector<VPointF> m_points;
+ std::vector<VPath::Element> m_elements;
+ int m_segments;
+ VPointF mStartPoint;
+ bool mNewSegment;
};
vcow_ptr<VPathData> d;
};
-inline bool VPath::isEmpty()const
+inline bool VPath::isEmpty() const
{
return d->isEmpty();
}
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));
}
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);
}
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);
}
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::Element> &VPath::elements() const
V_END_NAMESPACE
-#endif // VPATH_H
+#endif // VPATH_H
-#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
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
#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 "<<o.x()<<","<<o.y()<<"}";
+ os << "{P " << o.x() << "," << o.y() << "}";
return os;
}
inline VPointF &VPointF::operator+=(const VPointF &p) noexcept
-{ mx+=p.mx; my+=p.my; return *this; }
+{
+ mx += p.mx;
+ my += p.my;
+ return *this;
+}
inline VPointF &VPointF::operator-=(const VPointF &p) noexcept
-{ mx-=p.mx; my-=p.my; return *this; }
-
-class VPoint
{
+ mx -= p.mx;
+ my -= p.my;
+ return *this;
+}
+
+class VPoint {
public:
- constexpr inline VPoint() noexcept :mx(0), my(0){}
- constexpr inline VPoint(int x, int y) noexcept :mx(x), my(y){}
- constexpr inline int x() const noexcept {return mx;}
- constexpr inline int y() const noexcept {return my;}
- inline void setX(int x) {mx = x;}
- inline void setY(int y) {my = y;}
- inline VPoint &operator+=(const VPoint &p) noexcept;
- inline VPoint &operator-=(const VPoint &p) noexcept;
+ constexpr inline VPoint() noexcept : mx(0), my(0) {}
+ constexpr inline VPoint(int x, int y) noexcept : mx(x), my(y) {}
+ constexpr inline int x() const noexcept { return mx; }
+ constexpr inline int y() const noexcept { return my; }
+ inline void setX(int x) { mx = x; }
+ inline void setY(int y) { my = y; }
+ inline VPoint & operator+=(const VPoint &p) noexcept;
+ inline VPoint & operator-=(const VPoint &p) noexcept;
constexpr inline bool operator==(const VPoint &o) const;
- constexpr inline bool operator!=(const VPoint &o) const { return !(operator==(o)); }
- friend inline VPoint operator-(const VPoint &p1, const VPoint &p2);
- inline friend VDebug& operator<<(VDebug& os, const VPoint& o);
+ constexpr inline bool operator!=(const VPoint &o) const
+ {
+ return !(operator==(o));
+ }
+ friend inline VPoint operator-(const VPoint &p1, const VPoint &p2);
+ inline friend VDebug &operator<<(VDebug &os, const VPoint &o);
+
private:
int mx;
int my;
};
-inline VDebug& operator<<(VDebug& os, const VPoint& o)
+inline VDebug &operator<<(VDebug &os, const VPoint &o)
{
- os<<"{P "<<o.x()<<","<<o.y()<<"}";
+ os << "{P " << o.x() << "," << o.y() << "}";
return os;
}
inline VPoint operator-(const VPoint &p1, const VPoint &p2)
{
- return VPoint(p1.mx-p2.mx, p1.my-p2.my);
+ return VPoint(p1.mx - p2.mx, p1.my - p2.my);
}
-constexpr inline bool VPoint::operator ==(const VPoint &o) const
+constexpr inline bool VPoint::operator==(const VPoint &o) const
{
return (mx == o.x() && my == o.y());
}
inline VPoint &VPoint::operator+=(const VPoint &p) noexcept
-{ mx+=p.mx; my+=p.my; return *this; }
+{
+ mx += p.mx;
+ my += p.my;
+ return *this;
+}
inline VPoint &VPoint::operator-=(const VPoint &p) noexcept
-{ mx-=p.mx; my-=p.my; return *this; }
-
-
-class VSize
{
+ mx -= p.mx;
+ my -= p.my;
+ return *this;
+}
+
+class VSize {
public:
- constexpr inline VSize() noexcept :mw(0), mh(0){}
- constexpr inline VSize(int w, int h) noexcept :mw(w), mh(h){}
- constexpr inline int width() const noexcept {return mw;}
- constexpr inline int height() const noexcept {return mh;}
- inline void setWidth(int w) {mw = w;}
- inline void setHeight(int h) {mh = h;}
- inline VSize &operator+=(const VSize &p) noexcept;
- inline VSize &operator-=(const VSize &p) noexcept;
+ constexpr inline VSize() noexcept : mw(0), mh(0) {}
+ constexpr inline VSize(int w, int h) noexcept : mw(w), mh(h) {}
+ constexpr inline int width() const noexcept { return mw; }
+ constexpr inline int height() const noexcept { return mh; }
+ inline void setWidth(int w) { mw = w; }
+ inline void setHeight(int h) { mh = h; }
+ inline VSize & operator+=(const VSize &p) noexcept;
+ inline VSize & operator-=(const VSize &p) noexcept;
constexpr inline bool operator==(const VSize &o) const;
- constexpr inline bool operator!=(const VSize &o) const { return !(operator==(o)); }
- inline friend VDebug& operator<<(VDebug& os, const VSize& o);
+ constexpr inline bool operator!=(const VSize &o) const
+ {
+ return !(operator==(o));
+ }
+ inline friend VDebug &operator<<(VDebug &os, const VSize &o);
+
private:
int mw;
int mh;
};
-inline VDebug& operator<<(VDebug& os, const VSize& o)
+inline VDebug &operator<<(VDebug &os, const VSize &o)
{
- os<<"{P "<<o.width()<<","<<o.height()<<"}";
+ os << "{P " << o.width() << "," << o.height() << "}";
return os;
}
-constexpr inline bool VSize::operator ==(const VSize &o) const
+constexpr inline bool VSize::operator==(const VSize &o) const
{
return (mw == o.width() && mh == o.height());
}
inline VSize &VSize::operator+=(const VSize &p) noexcept
-{ mw+=p.mw; mh+=p.mh; return *this; }
+{
+ mw += p.mw;
+ mh += p.mh;
+ return *this;
+}
inline VSize &VSize::operator-=(const VSize &p) noexcept
-{ mw-=p.mw; mh-=p.mh; return *this; }
+{
+ mw -= p.mw;
+ mh -= p.mh;
+ return *this;
+}
V_END_NAMESPACE
-#endif // VPOINT_H
+#endif // VPOINT_H
-#include"vraster.h"
-#include"v_ft_raster.h"
-#include"v_ft_stroker.h"
-#include"vpath.h"
-#include"vmatrix.h"
-#include<cstring>
-#include"vdebug.h"
-#include"vtaskqueue.h"
-#include<thread>
+#include "vraster.h"
+#include <cstring>
+#include <thread>
+#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;
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()
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
void FTOutline::convert(const VPath &path)
{
const std::vector<VPath::Element> &elements = path.elements();
- const std::vector<VPointF> &points = path.points();
+ const std::vector<VPointF> & 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++;
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();
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)
{
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());
}
}
-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<VRle> sender;
- std::future<VRle> 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<VRle> sender;
+ std::future<VRle> 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;
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) {
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;
}
class RleTaskScheduler {
- const unsigned _count{std::thread::hardware_concurrency()};
- std::vector<std::thread> _threads;
+ const unsigned _count{std::thread::hardware_concurrency()};
+ std::vector<std::thread> _threads;
std::vector<TaskQueue<RleTask>> _q{_count};
- std::atomic<unsigned> _index{0};
+ std::atomic<unsigned> _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);
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<VRle> async(RleTask *task) {
+ std::future<VRle> async(RleTask *task)
+ {
auto receiver = std::move(task->receiver);
auto i = _index++;
return receiver;
}
- std::future<VRle> strokeRle(const VPath &path,
- CapStyle cap,
- JoinStyle join,
- float width,
- float meterLimit) {
+ std::future<VRle> strokeRle(const VPath &path, CapStyle cap, JoinStyle join,
+ float width, float meterLimit)
+ {
RleTask *task = new RleTask();
task->stroke = true;
task->path = path;
return async(task);
}
- std::future<VRle> fillRle(const VPath &path, FillRule fillRule) {
+ std::future<VRle> fillRle(const VPath &path, FillRule fillRule)
+ {
RleTask *task = new RleTask();
task->path = path;
task->fillRule = fillRule;
static RleTaskScheduler raster_scheduler;
-VRaster::VRaster()
-{
-}
+VRaster::VRaster() {}
-VRaster::~VRaster()
-{
-}
+VRaster::~VRaster() {}
-std::future<VRle>
-VRaster::generateFillInfo(const VPath &path, FillRule fillRule)
+std::future<VRle> VRaster::generateFillInfo(const VPath &path,
+ FillRule fillRule)
{
if (path.isEmpty()) {
std::promise<VRle> promise;
return raster_scheduler.fillRle(path, fillRule);
}
-std::future<VRle>
-VRaster::generateStrokeInfo(const VPath &path, CapStyle cap, JoinStyle join,
- float width, float meterLimit)
+std::future<VRle> VRaster::generateStrokeInfo(const VPath &path, CapStyle cap,
+ JoinStyle join, float width,
+ float meterLimit)
{
if (path.isEmpty()) {
std::promise<VRle> promise;
#ifndef VRASTER_H
#define VRASTER_H
-#include"vrle.h"
-#include<future>
+#include <future>
+#include "vrle.h"
V_BEGIN_NAMESPACE
class VPath;
struct VRasterPrivate;
-class VRaster
-{
+class VRaster {
public:
~VRaster();
static VRaster &instance()
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<VRle> generateFillInfo(const VPath &path,
+ FillRule fillRule = FillRule::Winding);
+ std::future<VRle> generateStrokeInfo(const VPath &path, CapStyle cap,
+ JoinStyle join, float width,
+ float meterLimit);
- std::future<VRle> generateFillInfo(const VPath &path, FillRule fillRule = FillRule::Winding);
- std::future<VRle> generateStrokeInfo(const VPath &path, CapStyle cap, JoinStyle join,
- float width, float meterLimit);
private:
VRaster();
};
V_END_NAMESPACE
-#endif // VRASTER_H
+#endif // VRASTER_H
#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;
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 "<<o.x()<<","<<o.y()<<","<<o.width()<<","<<o.height()<<"}";
+ os << "{R " << o.x() << "," << o.y() << "," << o.width() << ","
+ << o.height() << "}";
return os;
}
V_CONSTEXPR inline bool operator==(const VRect &r1, const VRect &r2) noexcept
{
- return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2;
+ return r1.x1 == r2.x1 && r1.x2 == r2.x2 && r1.y1 == r2.y1 && r1.y2 == r2.y2;
}
V_CONSTEXPR inline bool operator!=(const VRect &r1, const VRect &r2) noexcept
{
- return r1.x1!=r2.x1 || r1.x2!=r2.x2 || r1.y1!=r2.y1 || r1.y2!=r2.y2;
+ return r1.x1 != r2.x1 || r1.x2 != r2.x2 || r1.y1 != r2.y1 || r1.y2 != r2.y2;
}
V_CONSTEXPR inline bool VRect::isEmpty() const
-{ return x1 > 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)
{
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;
};
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
* PERFORMANCE OF THIS SOFTWARE.
*/
-#include <cstdint>
+#include <assert.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdio.h>
-#include <assert.h>
-
+#include <cstdint>
#define critical_if_fail assert
#define PIXMAN_EXPORT static
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
#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
*/
/* 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;
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;
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;
}
*
*-----------------------------------------------------------------------
*/
-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;
* 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;
/*
*/
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
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;
}
/* 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)
/*-
*
*-----------------------------------------------------------------------
*/
-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.
*-----------------------------------------------------------------------
*/
-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:
* 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;
- }
+ }
}
/*
* 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
*/
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.
* 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);
}
/*-
*
*-----------------------------------------------------------------------
*/
-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
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);
}
/*======================================================================
*-----------------------------------------------------------------------
*/
/*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)
/*======================================================================
*
*-----------------------------------------------------------------------
*/
-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;
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;
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;
}
*-----------------------------------------------------------------------
*/
/*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;
}
*
*-----------------------------------------------------------------------
*/
-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;
/* 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
* 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
/* 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);
}
}
* 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;
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;
}
}
* 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;
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;
};
void VRegion::detach()
{
- if (d->ref.isShared())
- *this = copy();
+ if (d->ref.isShared()) *this = copy();
}
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<VRegionData*>(&shared_empty))
-{
-}
+VRegion::VRegion() : d(const_cast<VRegionData *>(&shared_empty)) {}
VRegion::VRegion(int x, int y, int w, int h)
{
VRegion::VRegion(const VRect &r)
{
if (r.isEmpty()) {
- d = const_cast<VRegionData*>(&shared_empty);
+ d = const_cast<VRegionData *>(&shared_empty);
} else {
d = new VRegionData;
d->rgn = new VRegionPrivate;
d->ref.ref();
}
-VRegion::VRegion(VRegion &&other): d(other.d)
+VRegion::VRegion(VRegion &&other) : d(other.d)
{
- other.d = const_cast<VRegionData*>(&shared_empty);
-
+ other.d = const_cast<VRegionData *>(&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;
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<VRegionData*>(&shared_empty);
+ other.d = const_cast<VRegionData *>(&shared_empty);
return *this;
}
VRegion::~VRegion()
{
- if (!d->ref.deref())
- cleanUp(d);
+ if (!d->ref.deref()) cleanUp(d);
}
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());
{
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;
} 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);
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();
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();
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;
}
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;
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;
VRect VRegion::boundingRect() const noexcept
{
- if (isEmpty())
- return VRect();
+ if (isEmpty()) return VRect();
return box_to_rect(&d->rgn->extents);
}
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 = "<<o.boundingRect()<<"]";
- os<<"[rectCount = "<<o.rectCount()<<"]";
- os<<"[rects = ";
- for(int i=0; i< o.rectCount(); i++) {
- os<<o.rectAt(i);
+ os << "[REGION: "
+ << "[bbox = " << o.boundingRect() << "]";
+ os << "[rectCount = " << o.rectCount() << "]";
+ os << "[rects = ";
+ for (int i = 0; i < o.rectCount(); i++) {
+ os << o.rectAt(i);
}
- os<<"]"<<"]";
+ os << "]"
+ << "]";
return os;
-
}
V_END_NAMESPACE
-
#ifndef VREGION_H
#define VREGION_H
-#include"vdebug.h"
#include <vglobal.h>
-#include<vrect.h>
-#include<vpoint.h>
-#include<utility>
+#include <vpoint.h>
+#include <vrect.h>
+#include <utility>
+#include "vdebug.h"
V_BEGIN_NAMESPACE
struct VRegionData;
-class VRegion
-{
+class VRegion {
public:
VRegion();
VRegion(int x, int y, int w, int h);
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
#include "vrle.h"
-#include"vglobal.h"
-#include<vrect.h>
-#include<cstdlib>
-#include<vector>
-#include<array>
-#include<algorithm>
-#include"vdebug.h"
-#include"vregion.h"
+#include <vrect.h>
+#include <algorithm>
+#include <array>
+#include <cstdlib>
+#include <vector>
+#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
* 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;
}
/*
* 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)
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;
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<VRle::Span,256> 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<VRle::Span, 256> 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) {
} 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<uchar,1024> 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<uchar, 1024> 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--;
}
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<VRle::Span> m_spans;// array of Spanlines.
+ std::vector<VRle::Span> m_spans; // array of Spanlines.
VPoint mOffset;
- bool mBboxDirty;
+ bool mBboxDirty;
};
-inline static void
-copyArrayToVector(const VRle::Span *span, int count, std::vector<VRle::Span> &v)
+inline static void copyArrayToVector(const VRle::Span *span, int count,
+ std::vector<VRle::Span> &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="<<o.mOffset<<"]"<<
- "[span count ="<<o.m_spans.size()<<"]\n";
- os<<"[rle spans = {x y len coverage}";
- for(auto sp : o.m_spans)
- os<<"{"<<sp.x<<" "<<sp.y<<" "<<sp.len<<" "<<sp.coverage<<"}";
- os<<"]";
+ os << "[bbox=" << o.m_bbox << "]"
+ << "[offset=" << o.mOffset << "]"
+ << "[span count =" << o.m_spans.size() << "]\n";
+ os << "[rle spans = {x y len coverage}";
+ for (auto sp : o.m_spans)
+ os << "{" << sp.x << " " << sp.y << " " << sp.len << " " << sp.coverage
+ << "}";
+ os << "]";
return os;
}
void VRleImpl::translate(const VPoint &pt)
{
- //take care of last offset if applied
+ // take care of last offset if applied
mOffset = pt - mOffset;
int x = mOffset.x();
int y = mOffset.y();
{
VRect clip = r;
- VRleHelper tresult, tmp_obj;
- std::array<VRle::Span,256> array;
+ VRleHelper tresult, tmp_obj;
+ std::array<VRle::Span, 256> array;
- //setup the tresult object
+ // setup the tresult object
tresult.size = array.size();
tresult.alloc = array.size();
tresult.spans = array.data();
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<VRle::Span,256> array;
+ VRleHelper tresult, tmp_obj;
+ std::array<VRle::Span, 256> array;
- //setup the tresult object
+ // setup the tresult object
tresult.size = array.size();
tresult.alloc = array.size();
tresult.spans = array.data();
tmp_obj.spans = const_cast<VRle::Span *>(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<VRle::Span,256> array;
+ VRleHelper tresult, tmp_obj, tmp_clip;
+ std::array<VRle::Span, 256> array;
- //setup the tresult object
+ // setup the tresult object
tresult.size = array.size();
tresult.alloc = array.size();
tresult.spans = array.data();
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<VRle::Span *>(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();
}
// 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<VRle::Span,256> array;
+ VRleHelper tresult, tmp_obj, tmp_other;
+ std::array<VRle::Span, 256> array;
- //setup the tresult object
+ // setup the tresult object
tresult.size = array.size();
tresult.alloc = array.size();
tresult.spans = array.data();
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<VRle::Span *>(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);
}
result.mBboxDirty = false;
}
-
VRleImpl &VRleImpl::operator=(const VRleImpl &other)
{
m_spans = other.m_spans;
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;
return true;
}
-
void VRleImpl::updateBbox()
{
if (!mBboxDirty) return;
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)
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;
void VRle::detach()
{
- if (d->ref.isShared())
- *this = copy();
+ if (d->ref.isShared()) *this = copy();
}
VRle VRle::copy() const
VRle::~VRle()
{
- if (!d->ref.deref())
- cleanUp(d);
+ if (!d->ref.deref()) cleanUp(d);
}
-VRle::VRle()
- : d(const_cast<VRleData*>(&shared_empty))
-{
-}
+VRle::VRle() : d(const_cast<VRleData *>(&shared_empty)) {}
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<VRleData*>(&shared_empty);
+ other.d = const_cast<VRleData *>(&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;
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<VRleData*>(&shared_empty);
+ other.d = const_cast<VRleData *>(&shared_empty);
return *this;
}
-bool VRle::isEmpty()const
+bool VRle::isEmpty() const
{
return (d == &shared_empty || d->impl.m_spans.empty());
}
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;
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();
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();
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;
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();
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();
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 = "<<o.d->ref.count()<<"]"<<o.d->impl<<"]";
+ os << "[RLE: [dptr = "
+ << "o.d"
+ << "]"
+ << "[ref = " << o.d->ref.count() << "]" << o.d->impl << "]";
return os;
}
V_END_NAMESPACE
-
-
-
-
#ifndef VRLE_H
#define VRLE_H
-#include<vglobal.h>
-#include<vrect.h>
-#include<vpoint.h>
+#include <vglobal.h>
+#include <vpoint.h>
+#include <vrect.h>
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)
V_END_NAMESPACE
-#endif // VRLE_H
+#endif // VRLE_H
#ifndef VTASKQUEUE_H
#define VTASKQUEUE_H
-#include<deque>
+#include <deque>
template <typename Task>
class TaskQueue {
using lock_t = std::unique_lock<std::mutex>;
- std::deque<Task *> _q;
- bool _done{false};
- std::mutex _mutex;
+ std::deque<Task *> _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();
return true;
}
- bool try_push(Task *task) {
+ bool try_push(Task *task)
+ {
{
lock_t lock{_mutex, std::try_to_lock};
if (!lock) return false;
return true;
}
- void done() {
+ void done()
+ {
{
lock_t lock{_mutex};
_done = true;
_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);
}
};
-#endif // VTASKQUEUE_H
+#endif // VTASKQUEUE_H