2 #include"v_ft_raster.h"
3 #include"v_ft_stroker.h"
13 FTOutline(int points, int segments)
15 ft.points = new SW_FT_Vector[points + segments];
16 ft.tags = new char[points + segments];
17 ft.contours = new short[segments];
18 ft.n_points = ft.n_contours = 0;
21 void moveTo(const VPointF &pt);
22 void lineTo(const VPointF &pt);
23 void cubicTo(const VPointF &ctr1, const VPointF &ctr2, const VPointF end);
26 void transform(const VMatrix &m);
37 #define TO_FT_COORD(x) ((x) * 64) // to freetype 26.6 coordinate.
39 void FTOutline::transform(const VMatrix &m)
42 if (m.isIdentity()) return;
43 for (auto i = 0; i < ft.n_points; i++) {
44 pt = m.map(VPointF(ft.points[i].x/64.0, ft.points[i].y/64.0));
45 ft.points[i].x = TO_FT_COORD(pt.x());
46 ft.points[i].y = TO_FT_COORD(pt.y());
50 void FTOutline::moveTo(const VPointF &pt)
52 ft.points[ft.n_points].x = TO_FT_COORD(pt.x());
53 ft.points[ft.n_points].y = TO_FT_COORD(pt.y());
54 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
56 ft.contours[ft.n_contours] = ft.n_points - 1;
63 void FTOutline::lineTo(const VPointF &pt)
65 ft.points[ft.n_points].x = TO_FT_COORD(pt.x());
66 ft.points[ft.n_points].y = TO_FT_COORD(pt.y());
67 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
72 void FTOutline::cubicTo(const VPointF &cp1, const VPointF &cp2, const VPointF ep)
74 ft.points[ft.n_points].x = TO_FT_COORD(cp1.x());
75 ft.points[ft.n_points].y = TO_FT_COORD(cp1.y());
76 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_CUBIC;
79 ft.points[ft.n_points].x = TO_FT_COORD(cp2.x());
80 ft.points[ft.n_points].y = TO_FT_COORD(cp2.y());
81 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_CUBIC;
84 ft.points[ft.n_points].x = TO_FT_COORD(ep.x());
85 ft.points[ft.n_points].y = TO_FT_COORD(ep.y());
86 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
90 void FTOutline::close()
94 index = ft.contours[ft.n_contours - 1] + 1;
99 // make sure atleast 1 point exists in the segment.
100 if (ft.n_points == index) {
105 ft.points[ft.n_points].x = ft.points[index].x;
106 ft.points[ft.n_points].y = ft.points[index].y;
107 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
112 void FTOutline::end()
115 ft.contours[ft.n_contours] = ft.n_points - 1;
120 struct VRasterPrivate
123 VRle generateFillInfoAsync(const SW_FT_Outline *outline);
124 VRle generateStrokeInfoAsync(const SW_FT_Outline *outline, SW_FT_Stroker_LineCap cap,
125 SW_FT_Stroker_LineJoin join,
126 int width, int meterLimit,
129 std::mutex m_rasterAcess;
130 std::mutex m_strokerAcess;
131 SW_FT_Raster m_raster;
132 SW_FT_Stroker m_stroker;
142 rleGenerationCb( int count, const SW_FT_Span* spans,void *user)
144 VRle *rle = (VRle *) user;
145 VRle::Span *rleSpan = (VRle::Span *)spans;
146 rle->addSpan(rleSpan, count);
149 VRle VRasterPrivate::generateFillInfoAsync(const SW_FT_Outline *outline)
151 m_rasterAcess.lock();
153 SW_FT_Raster_Params params;
155 params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA ;
156 params.gray_spans = &rleGenerationCb;
158 params.source = outline;
160 sw_ft_grays_raster.raster_render(m_raster, ¶ms);
162 m_rasterAcess.unlock();
167 VRle VRasterPrivate::generateStrokeInfoAsync(const SW_FT_Outline *outline, SW_FT_Stroker_LineCap cap,
168 SW_FT_Stroker_LineJoin join,
169 int width, int meterLimit,
172 m_strokerAcess.lock();
174 SW_FT_Outline strokeOutline = { 0, 0, nullptr, nullptr, nullptr, SW_FT_OUTLINE_NONE };
176 SW_FT_Stroker_Set(m_stroker, width, cap, join, meterLimit);
177 SW_FT_Stroker_ParseOutline(m_stroker, outline, !closed);
178 SW_FT_Stroker_GetCounts(m_stroker,&points, &contors);
180 strokeOutline.points = (SW_FT_Vector *) calloc(points, sizeof(SW_FT_Vector));
181 strokeOutline.tags = (char *) calloc(points, sizeof(char));
182 strokeOutline.contours = (short *) calloc(contors, sizeof(short));
184 SW_FT_Stroker_Export(m_stroker, &strokeOutline);
186 m_strokerAcess.unlock();
188 VRle rle = generateFillInfoAsync(&strokeOutline);
190 // cleanup the outline data.
191 free(strokeOutline.points);
192 free(strokeOutline.tags);
193 free(strokeOutline.contours);
201 d = new VRasterPrivate;
202 sw_ft_grays_raster.raster_new(&d->m_raster);
203 SW_FT_Stroker_New(&d->m_stroker);
204 SW_FT_Stroker_Set(d->m_stroker, 1 << 6,
205 SW_FT_STROKER_LINECAP_BUTT, SW_FT_STROKER_LINEJOIN_MITER, 0);
210 sw_ft_grays_raster.raster_done(d->m_raster);
211 SW_FT_Stroker_Done(d->m_stroker);
214 void VRaster::deleteFTOutline(FTOutline *outline)
219 FTOutline *VRaster::toFTOutline(const VPath &path)
224 const std::vector<VPath::Element> &elements = path.elements();
225 const std::vector<VPointF> &points = path.points();
227 FTOutline *outline = new FTOutline(points.size(), path.segments());
230 for(auto element : elements) {
232 case VPath::Element::MoveTo:
233 outline->moveTo(points[index]);
236 case VPath::Element::LineTo:
237 outline->lineTo(points[index]);
240 case VPath::Element::CubicTo:
241 outline->cubicTo(points[index], points[index+1], points[index+2]);
244 case VPath::Element::Close:
255 VRle VRaster::generateFillInfo(const FTOutline *outline, FillRule fillRule)
257 int fillRuleFlag = SW_FT_OUTLINE_NONE;
259 case FillRule::EvenOdd:
260 fillRuleFlag = SW_FT_OUTLINE_EVEN_ODD_FILL;
263 fillRuleFlag = SW_FT_OUTLINE_NONE;
266 FTOutline *outlineRef = const_cast<FTOutline *>(outline);
267 outlineRef->ft.flags = fillRuleFlag;
268 return d->generateFillInfoAsync(&outlineRef->ft);
271 VRle VRaster::generateStrokeInfo(const FTOutline *outline, CapStyle cap, JoinStyle join,
272 float width, float meterLimit)
274 SW_FT_Stroker_LineCap ftCap;
275 SW_FT_Stroker_LineJoin ftJoin;
278 SW_FT_Bool ftbool = (SW_FT_Bool) outline->closed;
280 // map strokeWidth to freetype. It uses as the radius of the pen not the diameter
282 // convert to freetype co-ordinate
283 ftWidth = int(width * 64);
284 ftMeterLimit = int(meterLimit * 64);
286 // map to freetype capstyle
289 case CapStyle::Square:
290 ftCap = SW_FT_STROKER_LINECAP_SQUARE;
292 case CapStyle::Round:
293 ftCap = SW_FT_STROKER_LINECAP_ROUND;
296 ftCap = SW_FT_STROKER_LINECAP_BUTT;
301 case JoinStyle::Bevel:
302 ftJoin = SW_FT_STROKER_LINEJOIN_BEVEL;
304 case JoinStyle::Round:
305 ftJoin = SW_FT_STROKER_LINEJOIN_ROUND;
308 ftJoin = SW_FT_STROKER_LINEJOIN_MITER;
312 return d->generateStrokeInfoAsync(&outline->ft, ftCap, ftJoin,
313 ftWidth, ftMeterLimit, ftbool);