Merge pull request #6 from syncfusion/development

Added support for converting HTML to SVG
This commit is contained in:
George Livingston 2016-03-14 00:54:52 -04:00
Родитель 95ca7660c9 1316cc9286
Коммит eedfe330b7
5 изменённых файлов: 153 добавлений и 30 удалений

Просмотреть файл

@ -895,7 +895,9 @@ bool QSvgPaintEngine::end()
void QSvgPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm,
const QRectF &sr)
{
drawImage(r, pm.toImage(), sr);
QRect sourceRect = sr.toRect();
QPixmap pixmap = sourceRect != pm.rect() ? pm.copy(sourceRect) : pm;
drawImage(r, pixmap.toImage(), sr);
}
void QSvgPaintEngine::drawImage(const QRectF &r, const QImage &image,

Просмотреть файл

@ -159,19 +159,6 @@ float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int
return beforeWidth;
}
void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
// This glyph buffer holds our glyphs+advances+font data for each glyph.
GlyphBuffer glyphBuffer;
float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer);
if (glyphBuffer.isEmpty())
return;
FloatPoint startPoint(startX, point.y());
drawGlyphBuffer(context, run, glyphBuffer, startPoint);
}
void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
{

Просмотреть файл

@ -41,7 +41,6 @@ struct ExpectedTextRunSize {
RefPtr<TextRun::RenderingContext> renderingContext;
};
COMPILE_ASSERT(sizeof(TextRun) == sizeof(ExpectedTextRunSize), TextRun_is_not_of_expected_size);
bool TextRun::s_allowsRoundingHacks = false;

Просмотреть файл

@ -62,6 +62,7 @@ public:
#if ENABLE(8BIT_TEXTRUN)
TextRun(const LChar* c, unsigned len, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding)
: m_charactersLength(len)
, m_characters(c)
, m_len(len)
, m_xpos(xpos)
#if ENABLE(SVG)
@ -85,6 +86,7 @@ public:
TextRun(const UChar* c, unsigned len, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding)
: m_charactersLength(len)
, m_characters(c)
, m_len(len)
, m_xpos(xpos)
#if ENABLE(SVG)
@ -107,6 +109,7 @@ public:
TextRun(const String& s, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding)
: m_charactersLength(s.length())
, m_characters(s.characters())
, m_len(s.length())
, m_xpos(xpos)
#if ENABLE(SVG)
@ -155,6 +158,13 @@ public:
return result;
}
UChar operator[](int i) const { ASSERT(i >= 0 && i < m_len); return m_characters[i]; }
const UChar* data(int i) const { ASSERT(i >= 0 && i < m_len); return &m_characters[i]; }
const UChar* characters() const { return m_characters; }
void setText(const UChar* c, int len) { m_characters = c; m_len = len; }
UChar operator[](unsigned i) const { ASSERT_WITH_SECURITY_IMPLICATION(i < m_len); return is8Bit() ? m_data.characters8[i] :m_data.characters16[i]; }
const LChar* data8(unsigned i) const { ASSERT_WITH_SECURITY_IMPLICATION(i < m_len); ASSERT(is8Bit()); return &m_data.characters8[i]; }
const UChar* data16(unsigned i) const { ASSERT_WITH_SECURITY_IMPLICATION(i < m_len); ASSERT(!is8Bit()); return &m_data.characters16[i]; }
@ -227,7 +237,7 @@ public:
private:
static bool s_allowsRoundingHacks;
const UChar* m_characters;
union {
const LChar* characters8;
const UChar* characters16;

Просмотреть файл

@ -37,6 +37,8 @@
#include "TextRun.h"
#include <QBrush>
#include <QPaintDevice>
#include <QPaintEngine>
#include <QPainter>
#include <QPainterPath>
#include <QPen>
@ -173,6 +175,96 @@ static void drawQtGlyphRun(GraphicsContext* context, const QGlyphRun& qtGlyphRun
}
}
static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to, const QFont& font, bool isComplexText)
{
if (to < 0)
to = run.length();
QPainter *p = ctx->platformContext();
QPen textFillPen;
if (ctx->textDrawingMode() & TextModeFill)
textFillPen = fillPenForContext(ctx);
QPen textStrokePen;
if (ctx->textDrawingMode() & TextModeStroke)
textStrokePen = strokePenForContext(ctx);
String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
QPointF pt(point.x(), point.y());
p->setFont(font);
int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
if (!isComplexText && !(ctx->textDrawingMode() & TextModeStroke))
flags |= Qt::TextBypassShaping;
if (from > 0 || to < run.length()) {
if (isComplexText) {
QTextLayout layout(string, font);
QTextLine line = setupLayout(&layout, run,false);
float x1 = line.cursorToX(from);
float x2 = line.cursorToX(to);
if (x2 < x1)
qSwap(x1, x2);
QFontMetrics fm(font);
int ascent = fm.ascent();
QRectF boundingRect(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
QRectF clip = boundingRect;
QPainterPath textStrokePath;
if (ctx->textDrawingMode() & TextModeStroke)
textStrokePath.addText(pt, font, string);
if (ctx->hasShadow()) {
const GraphicsContextState& state = ctx->state();
if (ctx->mustUseShadowBlur()) {
ShadowBlur shadow(state);
GraphicsContext* shadowContext = shadow.beginShadowLayer(ctx, boundingRect);
if (shadowContext) {
QPainter* shadowPainter = shadowContext->platformContext();
shadowPainter->setPen(state.shadowColor);
if (shadowContext->textDrawingMode() & TextModeFill)
shadowPainter->drawText(pt, string, flags, run.expansion());
else if (shadowContext->textDrawingMode() & TextModeStroke)
shadowPainter->strokePath(textStrokePath, shadowPainter->pen());
shadow.endShadowLayer(ctx);
}
}
else {
QPen previousPen = p->pen();
p->setPen(state.shadowColor);
const QPointF shadowOffset(state.shadowOffset.width(), state.shadowOffset.height());
p->translate(shadowOffset);
if (ctx->textDrawingMode() & TextModeFill)
p->drawText(pt, string, flags, run.expansion());
else if (ctx->textDrawingMode() & TextModeStroke)
p->strokePath(textStrokePath, p->pen());
p->translate(-shadowOffset);
p->setPen(previousPen);
}
}
p->setPen(textFillPen);
line.draw(p, pt);
p->restore();
return;
}
int skipWidth = QFontMetrics(font).width(string, from, Qt::TextBypassShaping);
pt.setX(pt.x() + skipWidth);
string = fromRawDataWithoutRef(sanitized, from, to - from);
}
if (ctx->textDrawingMode() & TextModeFill) {
QPen previousPen = p->pen();
p->setPen(textFillPen);
p->drawText(pt, string, flags, run.expansion());
p->setPen(previousPen);
}
}
class TextLayout {
public:
static bool isNeeded(RenderText* text, const Font& font)
@ -234,20 +326,7 @@ float Font::width(TextLayout& layout, unsigned from, unsigned len, HashSet<const
return layout.width(from, len, fallbackFonts);
}
void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
{
String sanitized = Font::normalizeSpaces(run.characters16(), run.length());
const QString string = fromRawDataWithoutRef(sanitized);
QTextLayout layout(string);
layout.setRawFont(rawFont());
initFormatForTextLayout(&layout, run);
QTextLine line = setupLayout(&layout, run, true);
const QPointF adjustedPoint(point.x(), point.y() - line.ascent());
QList<QGlyphRun> runs = line.glyphRuns(from, to - from);
Q_FOREACH(QGlyphRun glyphRun, runs)
drawQtGlyphRun(ctx, glyphRun, adjustedPoint, line.ascent());
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
{
@ -379,6 +458,53 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* fontData,
}
void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
// This glyph buffer holds our glyphs+advances+font data for each glyph.
QPainter* painter = context->platformContext();
if (painter->paintEngine()->type() == QPaintEngine::SVG)
{
drawTextCommon(context, run, point, from, to, syntheticFont(),/*font(), /* isComplexText = */false);
}
else
{
GlyphBuffer glyphBuffer;
float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer);
if (glyphBuffer.isEmpty())
return;
FloatPoint startPoint(startX, point.y());
drawGlyphBuffer(context, run, glyphBuffer, startPoint);
}
}
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
QPainter* painter = context->platformContext();
if (painter->paintEngine()->type() == QPaintEngine::SVG)
{
drawTextCommon(context, run, point, from, to, syntheticFont(),/*font(), /* isComplexText = */true);
}
else
{
String sanitized = Font::normalizeSpaces(run.characters16(), run.length());
const QString string = fromRawDataWithoutRef(sanitized);
QTextLayout layout(string);
layout.setRawFont(rawFont());
initFormatForTextLayout(&layout, run);
QTextLine line = setupLayout(&layout, run, true);
const QPointF adjustedPoint(point.x(), point.y() - line.ascent());
QList<QGlyphRun> runs = line.glyphRuns(from, to - from);
Q_FOREACH(QGlyphRun glyphRun, runs)
drawQtGlyphRun(context, glyphRun, adjustedPoint, line.ascent());
}
}
bool Font::canExpandAroundIdeographsInComplexText()
{
return false;
@ -399,7 +525,6 @@ QFont Font::syntheticFont() const
return f;
}
QRawFont Font::rawFont() const
{
return primaryFont()->getQtRawFont();