mirror of
https://github.com/google/pebble.git
synced 2025-04-30 07:21:39 -04:00
243 lines
10 KiB
C
243 lines
10 KiB
C
/*
|
||
* Copyright 2024 Google LLC
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*/
|
||
|
||
#pragma once
|
||
|
||
#include "gtypes.h"
|
||
#include "text_layout_private.h"
|
||
#include "text_resources.h"
|
||
|
||
#define GDRAWMASK_BITS_PER_PIXEL PBL_IF_COLOR_ELSE(2, 1)
|
||
#define GDRAWMASK_PIXELS_PER_BYTE (8 / GDRAWMASK_BITS_PER_PIXEL)
|
||
|
||
//! @internal
|
||
typedef struct FrameBuffer FrameBuffer;
|
||
|
||
//! @internal
|
||
typedef struct GContext {
|
||
GBitmap dest_bitmap;
|
||
|
||
//! Which framebuffer dest_bitmap points into. This may be null if the
|
||
//! bitmap doesn't point into a framebuffer.
|
||
FrameBuffer* parent_framebuffer;
|
||
|
||
//! Number of rows between the top of the dest_bitmap and the top of it's
|
||
//! parent framebuffer. This value is invalid if parent_framebuffer is null.
|
||
uint8_t parent_framebuffer_vertical_offset;
|
||
|
||
// Keep state here for drawing commands:
|
||
GDrawState draw_state;
|
||
|
||
TextDrawState text_draw_state;
|
||
|
||
FontCache font_cache;
|
||
|
||
//! When the frame buffer accessed directly all graphics functions using this
|
||
//! context are locked
|
||
bool lock;
|
||
} GContext;
|
||
|
||
//! @internal
|
||
typedef enum {
|
||
GContextInitializationMode_App,
|
||
GContextInitializationMode_System,
|
||
} GContextInitializationMode;
|
||
|
||
//! @internal
|
||
typedef enum {
|
||
//! Pixels within the range are considered to be fully opaque
|
||
GDrawMaskRowInfoType_Opaque,
|
||
//! The opacity of the pixels within the range varies and needs individual checks
|
||
GDrawMaskRowInfoType_SemiTransparent,
|
||
} GDrawMaskRowInfoType;
|
||
|
||
//! @internal
|
||
//! Describes mask values for a given scan line.
|
||
//! The sole purpose of this data structure is performance optimization so that callers don't need
|
||
//! to test every single pixel on a GDrawMask's pixel_mask_data.
|
||
typedef struct {
|
||
//! Describes how to treat the range between .min_x and .max_x
|
||
GDrawMaskRowInfoType type;
|
||
//! Left-most pixel, 3.0 means that pixel 3 is fully visible, 3.5 means it's half visible
|
||
Fixed_S16_3 min_x;
|
||
//! Right-most pixel, 10.7 means that pixel 10 is fully opaque
|
||
Fixed_S16_3 max_x;
|
||
} GDrawMaskRowInfo;
|
||
|
||
//! @internal
|
||
//! Describes how draw operations in GDrawRawImplementation should treat the final opacity
|
||
//! conceptually. Each pixel's alpha value should be multiplied with the corresponding
|
||
//! .pixel_mask_data of this struct.
|
||
typedef struct GDrawMask {
|
||
//! Describes the mask values for each of the scan lines
|
||
GDrawMaskRowInfo *mask_row_infos;
|
||
//! Pixel mask that follows the structure and size of the actual framebuffer
|
||
void *pixel_mask_data;
|
||
//! A contiguous block of data that contains .row_infos and .pixel_mask_data
|
||
uint8_t data[];
|
||
} GDrawMask;
|
||
|
||
//! @addtogroup Graphics
|
||
//! @{
|
||
|
||
//! @addtogroup GraphicsContext Graphics Context
|
||
//! \brief The "canvas" into which an application draws
|
||
//!
|
||
//! The Pebble OS graphics engine, inspired by several notable graphics systems, including
|
||
//! Apple’s Quartz 2D and its predecessor QuickDraw, provides your app with a canvas into
|
||
//! which to draw, namely, the graphics context. A graphics context is the target into which
|
||
//! graphics functions can paint, using Pebble drawing routines (see \ref Drawing,
|
||
//! \ref PathDrawing and \ref TextDrawing).
|
||
//!
|
||
//! A graphics context holds a reference to the bitmap into which to paint. It also holds the
|
||
//! current drawing state, like the current fill color, stroke color, clipping box, drawing box,
|
||
//! compositing mode, and so on. The GContext struct is the type representing the graphics context.
|
||
//!
|
||
//! For drawing in your Pebble watchface or watchapp, you won't need to create a GContext
|
||
//! yourself. In most cases, it is provided by Pebble OS as an argument passed into a render
|
||
//! callback (the .update_proc of a Layer).
|
||
//!
|
||
//! Your app can’t call drawing functions at any given point in time: Pebble OS will request your
|
||
//! app to render. Typically, your app will be calling out to graphics functions in
|
||
//! the .update_proc callback of a Layer.
|
||
//! @see \ref Layer
|
||
//! @see \ref Drawing
|
||
//! @see \ref PathDrawing
|
||
//! @see \ref TextDrawing
|
||
//! @{
|
||
|
||
|
||
//! @internal
|
||
void graphics_context_init(GContext *ctx, FrameBuffer *framebuffer,
|
||
GContextInitializationMode init_mode);
|
||
|
||
//! @internal
|
||
void graphics_context_set_default_drawing_state(GContext *ctx,
|
||
GContextInitializationMode init_mode);
|
||
|
||
//! @internal
|
||
//! Gets the current drawing state (fill/stroke/text colors, compositing mode, ...)
|
||
GDrawState graphics_context_get_drawing_state(GContext* ctx);
|
||
|
||
//! @internal
|
||
//! Sets the current drawing state (fill/stroke/text colors, compositing mode, ...)
|
||
void graphics_context_set_drawing_state(GContext* ctx, GDrawState draw_state);
|
||
|
||
//! @internal
|
||
//! Move the drawing box origin by the translation offset specified
|
||
void graphics_context_move_draw_box(GContext* ctx, GPoint offset);
|
||
|
||
//! Sets the current stroke color of the graphics context.
|
||
//! @param ctx The graphics context onto which to set the stroke color
|
||
//! @param color The new stroke color
|
||
void graphics_context_set_stroke_color(GContext* ctx, GColor color);
|
||
void graphics_context_set_stroke_color_2bit(GContext* ctx, GColor2 color);
|
||
|
||
//! Sets the current fill color of the graphics context.
|
||
//! @param ctx The graphics context onto which to set the fill color
|
||
//! @param color The new fill color
|
||
void graphics_context_set_fill_color(GContext* ctx, GColor color);
|
||
void graphics_context_set_fill_color_2bit(GContext* ctx, GColor2 color);
|
||
|
||
//! Sets the current text color of the graphics context.
|
||
//! @param ctx The graphics context onto which to set the text color
|
||
//! @param color The new text color
|
||
void graphics_context_set_text_color(GContext* ctx, GColor color);
|
||
void graphics_context_set_text_color_2bit(GContext* ctx, GColor2 color);
|
||
|
||
//! Sets the tint color of the graphics context. This is used when drawing under
|
||
//! the GCompOpOr compositing mode.
|
||
//! @param ctx The graphics context onto which to set the tint color
|
||
//! @param color The new tint color
|
||
void graphics_context_set_tint_color(GContext *ctx, GColor color);
|
||
|
||
//! Sets the current bitmap compositing mode of the graphics context.
|
||
//! @param ctx The graphics context onto which to set the compositing mode
|
||
//! @param mode The new compositing mode
|
||
//! @see \ref GCompOp
|
||
//! @see \ref bitmap_layer_set_compositing_mode()
|
||
//! @note At the moment, this only affects the bitmaps drawing operations
|
||
//! -- \ref graphics_draw_bitmap_in_rect(), \ref graphics_draw_rotated_bitmap, and
|
||
//! anything that uses those APIs --, but it currently does not affect the filling or stroking
|
||
//! operations.
|
||
void graphics_context_set_compositing_mode(GContext* ctx, GCompOp mode);
|
||
|
||
//! Sets whether antialiasing is applied to stroke drawing
|
||
//! @param ctx The graphics context onto which to set the antialiasing
|
||
//! @param enable True = antialiasing enabled, False = antialiasing disabled
|
||
//! @note Default value is true.
|
||
void graphics_context_set_antialiased(GContext* ctx, bool enable);
|
||
|
||
//! @internal
|
||
//! Gets whether antialiasing is applied to stroke drawing
|
||
//! @param ctx The graphics context for which to get the current state of antialiasing
|
||
//! @return True if antialiasing is enabled, false otherwise
|
||
bool graphics_context_get_antialiased(GContext *ctx);
|
||
|
||
//! Sets the width of the stroke for drawing routines
|
||
//! @param ctx The graphics context onto which to set the stroke width
|
||
//! @param stroke_width Width in pixels of the stroke.
|
||
//! @note If stroke width of zero is passed, it will be ignored and will not change the value
|
||
//! stored in GContext. Currently, only odd stroke_width values are supported. If an even value
|
||
//! is passed in, the value will be stored as is, but the drawing routines will round down to the
|
||
//! previous integral value when drawing. Default value is 1.
|
||
void graphics_context_set_stroke_width(GContext* ctx, uint8_t stroke_width);
|
||
|
||
//! Instantiates and initializes a mask.
|
||
//! @param ctx The graphics context to use to initialize the new mask
|
||
//! @param transparent Whether the initial mask pixel values should all be transparent or opaque
|
||
//! @return The new clipping mask, or NULL on failure
|
||
GDrawMask *graphics_context_mask_create(const GContext *ctx, bool transparent);
|
||
|
||
//! Attaches a mask to the provided GContext for recording. Subsequent drawing operations will
|
||
//! change the mask values. The luminance of the drawing operations corresponds with the resulting
|
||
//! opacity in the mask, so the brighter a drawn pixel is, the more opaque its corresponding mask
|
||
//! value will be.
|
||
//! @param ctx The GContext to attach the mask to for recording
|
||
//! @param mask The mask to use for recording
|
||
//! @return True if the mask was successfully attached to the GContext for recording, false
|
||
//! otherwise
|
||
bool graphics_context_mask_record(GContext *ctx, GDrawMask *mask);
|
||
|
||
//! Attaches a mask to the provided GContext and activates it for subsequent drawing operations.
|
||
//! Upon activation, subsequent drawing operations will be multiplied with the given mask.
|
||
//! @param ctx The GContext to attach the mask to for use
|
||
//! @param mask The mask to use
|
||
//! @return True if the mask was successfully attached to the GContext for use, false otherwise
|
||
bool graphics_context_mask_use(GContext *ctx, GDrawMask *mask);
|
||
|
||
//! Destroys a previously created mask.
|
||
//! @param ctx The GContext the mask was used with
|
||
//! @param mask The mask to destroy
|
||
void graphics_context_mask_destroy(GContext *ctx, GDrawMask *mask);
|
||
|
||
//! @internal
|
||
//! Gets the size of the backing framebuffer for the graphics context or GSize(DISP_COLS, DISP_ROWS)
|
||
//! if there is no backing framebuffer.
|
||
GSize graphics_context_get_framebuffer_size(GContext *ctx);
|
||
|
||
//! @internal
|
||
//! Retrieves the destination bitmap for the graphics context.
|
||
//! @param ctx The graphics context to retrieve the bitmap for.
|
||
GBitmap* graphics_context_get_bitmap(GContext* ctx);
|
||
|
||
//! @internal
|
||
//! Updates the parent framebuffers dirty state based on a change to the
|
||
//! graphic context's bitmap.
|
||
void graphics_context_mark_dirty_rect(GContext* ctx, GRect rect);
|
||
|
||
//! @} // end addtogroup GraphicsContext
|
||
//! @} // end addtogroup Graphics
|