⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svgrootinlinebox.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* * This file is part of the WebKit project. * * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz> *           (C) 2006 Apple Computer Inc. *           (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */#include "config.h"#if ENABLE(SVG)#include "SVGRootInlineBox.h"#include "Editor.h"#include "Frame.h"#include "GraphicsContext.h"#include "RenderBlock.h"#include "RenderSVGRoot.h"#include "SVGInlineFlowBox.h"#include "SVGInlineTextBox.h"#include "SVGFontElement.h"#include "SVGPaintServer.h"#include "SVGRenderStyleDefs.h"#include "SVGRenderSupport.h"#include "SVGResourceFilter.h"#include "SVGTextPositioningElement.h"#include "SVGURIReference.h"#include "Text.h"#include "UnicodeRange.h"#include <float.h>// Text chunk creation is complex and the whole process// can easily be traced by setting this variable > 0.#define DEBUG_CHUNK_BUILDING 0namespace WebCore {static inline bool isVerticalWritingMode(const SVGRenderStyle* style){    return style->writingMode() == WM_TBRL || style->writingMode() == WM_TB; }static inline EAlignmentBaseline dominantBaselineToShift(bool isVerticalText, const RenderObject* text, const Font& font){    ASSERT(text);    const SVGRenderStyle* style = text->style() ? text->style()->svgStyle() : 0;    ASSERT(style);    const SVGRenderStyle* parentStyle = text->parent() && text->parent()->style() ? text->parent()->style()->svgStyle() : 0;    EDominantBaseline baseline = style->dominantBaseline();    if (baseline == DB_AUTO) {        if (isVerticalText)            baseline = DB_CENTRAL;        else            baseline = DB_ALPHABETIC;    }    switch (baseline) {    case DB_USE_SCRIPT:        // TODO: The dominant-baseline and the baseline-table components are set by        //       determining the predominant script of the character data content.        return AB_ALPHABETIC;    case DB_NO_CHANGE:    {        if (parentStyle)            return dominantBaselineToShift(isVerticalText, text->parent(), font);        ASSERT_NOT_REACHED();        return AB_AUTO;    }    case DB_RESET_SIZE:    {        if (parentStyle)            return dominantBaselineToShift(isVerticalText, text->parent(), font);        ASSERT_NOT_REACHED();        return AB_AUTO;        }    case DB_IDEOGRAPHIC:        return AB_IDEOGRAPHIC;    case DB_ALPHABETIC:        return AB_ALPHABETIC;    case DB_HANGING:        return AB_HANGING;    case DB_MATHEMATICAL:        return AB_MATHEMATICAL;    case DB_CENTRAL:        return AB_CENTRAL;    case DB_MIDDLE:        return AB_MIDDLE;    case DB_TEXT_AFTER_EDGE:        return AB_TEXT_AFTER_EDGE;    case DB_TEXT_BEFORE_EDGE:        return AB_TEXT_BEFORE_EDGE;    default:        ASSERT_NOT_REACHED();        return AB_AUTO;    }}static inline float alignmentBaselineToShift(bool isVerticalText, const RenderObject* text, const Font& font){    ASSERT(text);    const SVGRenderStyle* style = text->style() ? text->style()->svgStyle() : 0;    ASSERT(style);    const SVGRenderStyle* parentStyle = text->parent() && text->parent()->style() ? text->parent()->style()->svgStyle() : 0;    EAlignmentBaseline baseline = style->alignmentBaseline();    if (baseline == AB_AUTO) {        if (parentStyle && style->dominantBaseline() == DB_AUTO)            baseline = dominantBaselineToShift(isVerticalText, text->parent(), font);        else            baseline = dominantBaselineToShift(isVerticalText, text, font);        ASSERT(baseline != AB_AUTO);        }    // Note: http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling    switch (baseline) {    case AB_BASELINE:    {        if (parentStyle)            return dominantBaselineToShift(isVerticalText, text->parent(), font);        return 0.0f;    }    case AB_BEFORE_EDGE:    case AB_TEXT_BEFORE_EDGE:        return font.ascent();    case AB_MIDDLE:        return font.xHeight() / 2.0f;    case AB_CENTRAL:        // Not needed, we're taking this into account already for vertical text!        // return (font.ascent() - font.descent()) / 2.0f;        return 0.0f;    case AB_AFTER_EDGE:    case AB_TEXT_AFTER_EDGE:    case AB_IDEOGRAPHIC:        return font.descent();    case AB_ALPHABETIC:        return 0.0f;    case AB_HANGING:        return font.ascent() * 8.0f / 10.0f;    case AB_MATHEMATICAL:        return font.ascent() / 2.0f;    default:        ASSERT_NOT_REACHED();        return 0.0f;    }}static inline float glyphOrientationToAngle(const SVGRenderStyle* svgStyle, bool isVerticalText, const UChar& character){    switch (isVerticalText ? svgStyle->glyphOrientationVertical() : svgStyle->glyphOrientationHorizontal()) {    case GO_AUTO:    {        // Spec: Fullwidth ideographic and fullwidth Latin text will be set with a glyph-orientation of 0-degrees.        //       Text which is not fullwidth will be set with a glyph-orientation of 90-degrees.        unsigned int unicodeRange = findCharUnicodeRange(character);        if (unicodeRange == cRangeSetLatin || unicodeRange == cRangeArabic)            return 90.0f;        return 0.0f;    }    case GO_90DEG:        return 90.0f;    case GO_180DEG:        return 180.0f;    case GO_270DEG:        return 270.0f;    case GO_0DEG:    default:        return 0.0f;    }}static inline bool glyphOrientationIsMultiplyOf180Degrees(float orientationAngle){    return fabsf(fmodf(orientationAngle, 180.0f)) == 0.0f;}static inline float calculateGlyphAdvanceAndShiftRespectingOrientation(bool isVerticalText, float orientationAngle, float glyphWidth, float glyphHeight, const Font& font, SVGChar& svgChar, float& xOrientationShift, float& yOrientationShift){    bool orientationIsMultiplyOf180Degrees = glyphOrientationIsMultiplyOf180Degrees(orientationAngle);    // The function is based on spec requirements:    //    // Spec: If the 'glyph-orientation-horizontal' results in an orientation angle that is not a multiple of    // of 180 degrees, then the current text position is incremented according to the vertical metrics of the glyph.    //    // Spec: If if the 'glyph-orientation-vertical' results in an orientation angle that is not a multiple of    // 180 degrees,then the current text position is incremented according to the horizontal metrics of the glyph.    // vertical orientation handling    if (isVerticalText) {        if (orientationAngle == 0.0f) {            xOrientationShift = -glyphWidth / 2.0f;            yOrientationShift = font.ascent();        } else if (orientationAngle == 90.0f) {            xOrientationShift = -glyphHeight;            yOrientationShift = font.descent();            svgChar.orientationShiftY = -font.ascent();        } else if (orientationAngle == 270.0f) {            xOrientationShift = glyphHeight;            yOrientationShift = font.descent();            svgChar.orientationShiftX = -glyphWidth;            svgChar.orientationShiftY = -font.ascent();        } else if (orientationAngle == 180.0f) {            yOrientationShift = font.ascent();            svgChar.orientationShiftX = -glyphWidth / 2.0f;            svgChar.orientationShiftY = font.ascent() - font.descent();        }        // vertical advance calculation        if (orientationAngle != 0.0f && !orientationIsMultiplyOf180Degrees)            return glyphWidth;        return glyphHeight;     }    // horizontal orientation handling    if (orientationAngle == 90.0f) {        xOrientationShift = glyphWidth / 2.0f;        yOrientationShift = -font.descent();        svgChar.orientationShiftX = -glyphWidth / 2.0f - font.descent();         svgChar.orientationShiftY = font.descent();    } else if (orientationAngle == 270.0f) {        xOrientationShift = -glyphWidth / 2.0f;        yOrientationShift = -font.descent();        svgChar.orientationShiftX = -glyphWidth / 2.0f + font.descent();        svgChar.orientationShiftY = glyphHeight;    } else if (orientationAngle == 180.0f) {        xOrientationShift = glyphWidth / 2.0f;        svgChar.orientationShiftX = -glyphWidth / 2.0f;        svgChar.orientationShiftY = font.ascent() - font.descent();    }    // horizontal advance calculation    if (orientationAngle != 0.0f && !orientationIsMultiplyOf180Degrees)        return glyphHeight;    return glyphWidth;}static inline void startTextChunk(SVGTextChunkLayoutInfo& info){    info.chunk.boxes.clear();    info.chunk.boxes.append(SVGInlineBoxCharacterRange());    info.chunk.start = info.it;    info.assignChunkProperties = true;}static inline void closeTextChunk(SVGTextChunkLayoutInfo& info){    ASSERT(!info.chunk.boxes.last().isOpen());    ASSERT(info.chunk.boxes.last().isClosed());    info.chunk.end = info.it;    ASSERT(info.chunk.end >= info.chunk.start);    info.svgTextChunks.append(info.chunk);}RenderSVGRoot* findSVGRootObject(RenderObject* start){    // Find associated root inline box    while (start && !start->isSVGRoot())        start = start->parent();    ASSERT(start);    ASSERT(start->isSVGRoot());    return static_cast<RenderSVGRoot*>(start);}static inline FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>& chars){    return topLeftPositionOfCharacterRange(chars.begin(), chars.end());}FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>::iterator it, Vector<SVGChar>::iterator end){    float lowX = FLT_MAX, lowY = FLT_MAX;    for (; it != end; ++it) {        if (it->isHidden())            continue;        float x = (*it).x;        float y = (*it).y;        if (x < lowX)            lowX = x;        if (y < lowY)            lowY = y;    }    return FloatPoint(lowX, lowY);}// Helper functionstatic float calculateKerning(RenderObject* item){    const Font& font = item->style()->font();    const SVGRenderStyle* svgStyle = item->style()->svgStyle();    float kerning = 0.0f;    if (CSSPrimitiveValue* primitive = static_cast<CSSPrimitiveValue*>(svgStyle->kerning())) {        kerning = primitive->getFloatValue();        if (primitive->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE && font.pixelSize() > 0)            kerning = kerning / 100.0f * font.pixelSize();    }    return kerning;}// Helper class for paint()struct SVGRootInlineBoxPaintWalker {    SVGRootInlineBoxPaintWalker(SVGRootInlineBox* rootBox, SVGResourceFilter* rootFilter, RenderObject::PaintInfo paintInfo, int tx, int ty)        : m_rootBox(rootBox)        , m_chunkStarted(false)        , m_paintInfo(paintInfo)        , m_savedInfo(paintInfo)        , m_boundingBox(tx + rootBox->x(), ty + rootBox->y(), rootBox->width(), rootBox->height())        , m_filter(0)        , m_rootFilter(rootFilter)        , m_fillPaintServer(0)        , m_strokePaintServer(0)        , m_fillPaintServerObject(0)        , m_strokePaintServerObject(0)        , m_tx(tx)        , m_ty(ty)    {    }    ~SVGRootInlineBoxPaintWalker()    {        ASSERT(!m_filter);        ASSERT(!m_fillPaintServer);        ASSERT(!m_fillPaintServerObject);        ASSERT(!m_strokePaintServer);        ASSERT(!m_strokePaintServerObject);        ASSERT(!m_chunkStarted);    }    void teardownFillPaintServer()    {        if (!m_fillPaintServer)            return;        m_fillPaintServer->teardown(m_paintInfo.context, m_fillPaintServerObject, ApplyToFillTargetType, true);        m_fillPaintServer = 0;        m_fillPaintServerObject = 0;    }    void teardownStrokePaintServer()    {        if (!m_strokePaintServer)            return;        m_strokePaintServer->teardown(m_paintInfo.context, m_strokePaintServerObject, ApplyToStrokeTargetType, true);        m_strokePaintServer = 0;        m_strokePaintServerObject = 0;    }    void chunkStartCallback(InlineBox* box)    {        ASSERT(!m_chunkStarted);        m_chunkStarted = true;        InlineFlowBox* flowBox = box->parent();        // Initialize text rendering        RenderObject* object = flowBox->renderer();        ASSERT(object);        m_savedInfo = m_paintInfo;        m_paintInfo.context->save();        if (!flowBox->isRootInlineBox())            m_paintInfo.context->concatCTM(m_rootBox->renderer()->localTransform());        m_paintInfo.context->concatCTM(object->localTransform());        if (!flowBox->isRootInlineBox()) {            prepareToRenderSVGContent(object, m_paintInfo, m_boundingBox, m_filter, m_rootFilter);            m_paintInfo.rect = object->localTransform().inverse().mapRect(m_paintInfo.rect);        }    }    void chunkEndCallback(InlineBox* box)    {        ASSERT(m_chunkStarted);        m_chunkStarted = false;        InlineFlowBox* flowBox = box->parent();        RenderObject* object = flowBox->renderer();        ASSERT(object);        // Clean up last used paint server        teardownFillPaintServer();        teardownStrokePaintServer();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -