📄 platformcontextskia.cpp
字号:
/* * Copyright (c) 2008, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "GraphicsContext.h"#include "ImageBuffer.h"#include "NativeImageSkia.h"#include "PlatformContextSkia.h"#include "SkiaUtils.h"#include "skia/ext/image_operations.h"#include "skia/ext/platform_canvas.h"#include "SkBitmap.h"#include "SkColorPriv.h"#include "SkShader.h"#include "SkDashPathEffect.h"#include <wtf/MathExtras.h>// State -----------------------------------------------------------------------// Encapsulates the additional painting state information we store for each// pushed graphics state.struct PlatformContextSkia::State { State(); State(const State&); ~State(); // Common shader state. float m_alpha; SkPorterDuff::Mode m_porterDuffMode; SkShader* m_gradient; SkShader* m_pattern; bool m_useAntialiasing; SkDrawLooper* m_looper; // Fill. SkColor m_fillColor; // Stroke. WebCore::StrokeStyle m_strokeStyle; SkColor m_strokeColor; float m_strokeThickness; int m_dashRatio; // Ratio of the length of a dash to its width. float m_miterLimit; SkPaint::Cap m_lineCap; SkPaint::Join m_lineJoin; SkDashPathEffect* m_dash; // Text. (See cTextFill & friends in GraphicsContext.h.) int m_textDrawingMode; // Helper function for applying the state's alpha value to the given input // color to produce a new output color. SkColor applyAlpha(SkColor) const;#if defined(__linux__) || PLATFORM(WIN_OS) // If non-empty, the current State is clipped to this image. SkBitmap m_imageBufferClip; // If m_imageBufferClip is non-empty, this is the region the image is clipped to. WebCore::FloatRect m_clip;#endifprivate: // Not supported. void operator=(const State&);};// Note: Keep theses default values in sync with GraphicsContextState.PlatformContextSkia::State::State() : m_alpha(1) , m_porterDuffMode(SkPorterDuff::kSrcOver_Mode) , m_gradient(0) , m_pattern(0) , m_useAntialiasing(true) , m_looper(0) , m_fillColor(0xFF000000) , m_strokeStyle(WebCore::SolidStroke) , m_strokeColor(WebCore::Color::black) , m_strokeThickness(0) , m_dashRatio(3) , m_miterLimit(4) , m_lineCap(SkPaint::kDefault_Cap) , m_lineJoin(SkPaint::kDefault_Join) , m_dash(0) , m_textDrawingMode(WebCore::cTextFill){}PlatformContextSkia::State::State(const State& other) : m_alpha(other.m_alpha) , m_porterDuffMode(other.m_porterDuffMode) , m_gradient(other.m_gradient) , m_pattern(other.m_pattern) , m_useAntialiasing(other.m_useAntialiasing) , m_looper(other.m_looper) , m_fillColor(other.m_fillColor) , m_strokeStyle(other.m_strokeStyle) , m_strokeColor(other.m_strokeColor) , m_strokeThickness(other.m_strokeThickness) , m_dashRatio(other.m_dashRatio) , m_miterLimit(other.m_miterLimit) , m_lineCap(other.m_lineCap) , m_lineJoin(other.m_lineJoin) , m_dash(other.m_dash) , m_textDrawingMode(other.m_textDrawingMode)#if defined(__linux__) || PLATFORM(WIN_OS) , m_imageBufferClip(other.m_imageBufferClip) , m_clip(other.m_clip)#endif{ // Up the ref count of these. saveRef does nothing if 'this' is NULL. m_looper->safeRef(); m_dash->safeRef(); m_gradient->safeRef(); m_pattern->safeRef();}PlatformContextSkia::State::~State(){ m_looper->safeUnref(); m_dash->safeUnref(); m_gradient->safeUnref(); m_pattern->safeUnref();}SkColor PlatformContextSkia::State::applyAlpha(SkColor c) const{ int s = roundf(m_alpha * 256); if (s >= 256) return c; if (s < 0) return 0; int a = SkAlphaMul(SkColorGetA(c), s); return (c & 0x00FFFFFF) | (a << 24);}// PlatformContextSkia ---------------------------------------------------------// Danger: canvas can be NULL.PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas) : m_canvas(canvas) , m_stateStack(sizeof(State))#if PLATFORM(WIN_OS) , m_drawingToImageBuffer(false)#endif{ m_stateStack.append(State()); m_state = &m_stateStack.last();}PlatformContextSkia::~PlatformContextSkia(){}void PlatformContextSkia::setCanvas(skia::PlatformCanvas* canvas){ m_canvas = canvas;}#if PLATFORM(WIN_OS)void PlatformContextSkia::setDrawingToImageBuffer(bool value){ m_drawingToImageBuffer = value;}bool PlatformContextSkia::isDrawingToImageBuffer() const{ return m_drawingToImageBuffer;}#endifvoid PlatformContextSkia::save(){ m_stateStack.append(*m_state); m_state = &m_stateStack.last();#if defined(__linux__) || PLATFORM(WIN_OS) // The clip image only needs to be applied once. Reset the image so that we // don't attempt to clip multiple times. m_state->m_imageBufferClip.reset();#endif // Save our native canvas. canvas()->save();}#if defined(__linux__) || PLATFORM(WIN_OS)void PlatformContextSkia::beginLayerClippedToImage(const WebCore::FloatRect& rect, const WebCore::ImageBuffer* imageBuffer){ // Skia doesn't support clipping to an image, so we create a layer. The next // time restore is invoked the layer and |imageBuffer| are combined to // create the resulting image. m_state->m_clip = rect; SkRect bounds = { SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()), SkFloatToScalar(rect.right()), SkFloatToScalar(rect.bottom()) }; canvas()->saveLayerAlpha(&bounds, 255, static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag)); // Copy off the image as |imageBuffer| may be deleted before restore is invoked. const SkBitmap* bitmap = imageBuffer->context()->platformContext()->bitmap(); if (!bitmap->pixelRef()) { // The bitmap owns it's pixels. This happens when we've allocated the // pixels in some way and assigned them directly to the bitmap (as // happens when we allocate a DIB). In this case the assignment operator // does not copy the pixels, rather the copied bitmap ends up // referencing the same pixels. As the pixels may not live as long as we // need it to, we copy the image. bitmap->copyTo(&m_state->m_imageBufferClip, SkBitmap::kARGB_8888_Config); } else { // If there is a pixel ref, we can safely use the assignment operator. m_state->m_imageBufferClip = *bitmap; }}#endifvoid PlatformContextSkia::restore(){#if defined(__linux__) || PLATFORM(WIN_OS) if (!m_state->m_imageBufferClip.empty()) { applyClipFromImage(m_state->m_clip, m_state->m_imageBufferClip); canvas()->restore(); }#endif m_stateStack.removeLast(); m_state = &m_stateStack.last(); // Restore our native canvas. canvas()->restore();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -