📄 pw_draw.c
字号:
bits++; rx += 8; } y++; } IPW_TRACE_EXIT(DR2);}/** * Draws a bitmap with clipping. * @param gc pointer to graphic context * @param x x coord of bitmap's top left corner * @param y y coord of bitmap's top left corner * @param w bitmap's width * @param h bitmap's height * @param bits bitmap bits array * @param clip pointer to clip rectangle * @internal */ static void _DrawClipBitmap(Pw_GC* gc, Pw_Coord x, Pw_Coord y, Pw_Coord w, Pw_Coord h, Pw_Byte* bits, Pw_Rectangle* clip) { Pw_Coord w8;h = h; IPW_TRACE_ENTER(DR2); IPW_TRACE4(DR2, d, x, y, w, h); IPW_TRACE_RECT(DR2, clip); /* * Calculate bitmap's width in bytes and clip the top of the bitmap */ w8 = (w + 0x07) >> 3; bits += (clip->y - y) * w8; /* * When drawing a clipped bitmap we have two different cases: * * 1. the visible part of bitmap is greater then 8 pixels - then * we have some or none bits on left, 1 or more bytes in the * middle and some or none bits on the right. * * 2. the visible part is less then or equal 8 pixels - then the * visible bitmap bits can be all in one bitmap byte or can span * over two bytes. */ if (clip->w > 8) { /* The visible part is greater then 8 pixels */ Pw_uInt left_bytes, right_bytes, middle_bytes; Pw_uInt left_bits, right_bits, i, j; Pw_Coord cx; /* Calc bitmap's left side bytes and bits to clip */ left_bits = clip->x - x; left_bytes = left_bits >> 3; left_bits &= 0x07; /* Calc bitmap's right side bytes and bits to clip */ right_bits = x + (w8 << 3) - clip->x - clip->w; right_bytes = right_bits >> 3; right_bits &= 0x07; /* Calc bitmap's visible bytes */ middle_bytes = w8 - left_bytes - right_bytes; IPW_TRACE2(DR2, d, left_bits, right_bits); IPW_TRACE3(DR2, d, left_bytes, right_bytes, middle_bytes); if (left_bits != 0) middle_bytes--; if (right_bits != 0) { right_bits = 8 - right_bits; middle_bytes--; } /* Set x and y to top left corner of bitmap's visible part */ y = clip->y; x = clip->x - left_bits; /* Get left and right side visible bits mask */ left_bits = _bm_edgemask[0][left_bits]; right_bits = _bm_edgemask[1][right_bits]; /* Draw bitmap lines */ for (j = 0; j < clip->h; j++) { cx = x; /* Skip invisible bytes on left */ bits += left_bytes; if (left_bits != 0) { /* Draw visible bits on left */ gc->d.lld->draw_points(gc, cx, y, (*bits & left_bits)); bits++; cx += 8; } /* Draw visible bytes */ for (i = 0; i < middle_bytes; i++) { gc->d.lld->draw_points(gc, cx, y, *bits); bits++; cx += 8; } /* Draw visible bits on right */ if (right_bits != 0) { gc->d.lld->draw_points(gc, cx, y, (*bits & right_bits)); bits++; } /* Skip invisible bytes on right */ bits += right_bytes; y++; } } else { /* The visible part is less then or equal 8 pixels */ Pw_uInt i, mask; Pw_Byte left_bits, right_bits; /* Clip invisible bytes on left (in first visible line) */ bits += (clip->x - x) >> 3; /* Calc invisible bits on left */ left_bits = (clip->x - x) & 0x07; /* Calc the visible bits mask */ mask = _bm_edgemask[1][clip->w]; mask = (mask << 8) >> left_bits; /* Set x and y to top left corner of bitmap's visible part */ y = clip->y; x = clip->x - left_bits; /* Get the left and right part of visible bits mask */ left_bits = mask >> 8; right_bits = mask & 0x00FF; IPW_TRACE2(DR2, d, left_bits, right_bits); /* Draw bitmap lines */ for (i = 0; i < clip->h; i++) { /* If left part of mask has any visible bits draw them */ if (left_bits != 0) gc->d.lld->draw_points(gc, x, y, (*bits & left_bits)); /* Next bitmap's byte */ bits++; /* If right part of mask has any visible bits draw them */ if (right_bits != 0) gc->d.lld->draw_points(gc, x+8, y, (*bits & right_bits)); /* Skip invisible bytes on right and left */ bits += w8 - 1; y++; } } IPW_TRACE_EXIT(DR2);}/* -------------------------------------------------------------------------- */#if IPW_CHECK_EN(GC_STRUCT)Pw_Bool IPw_GCCheck(Pw_GC* gc){
return TRUE; /// !!!!! if (PW_NULL == gc->d.lld) { IPW_ASSERT(FALSE, ("GC (%p) lld == NULL!", gc)); return(FALSE); } if (PW_NULL == gc->d.lld->draw_point || PW_NULL == gc->d.lld->draw_points || PW_NULL == gc->d.lld->draw_hor_line || PW_NULL == gc->d.lld->draw_ver_line || PW_NULL == gc->d.lld->fill_rect) { IPW_ASSERT(FALSE, ("GC (%p) some lld funcs == NULL!", gc)); return(FALSE); } if (Pw_DrawableWindowType == gc->d.type && PW_NULL == gc->d.comp.window) { IPW_ASSERT(FALSE, ("GC (%p) window == NULL!", gc)); return(FALSE); } if (Pw_DrawableBitmapType == gc->d.type && PW_NULL == gc->d.comp.bitmap) { IPW_ASSERT(FALSE, ("GC (%p) bitmap == NULL!", gc)); return(FALSE); }/* if (PW_NULL == gc->color) { IPW_ASSERT(FALSE, ("GC (%p) color == NULL!", gc)); return(FALSE); } */ if (PW_NULL != gc->font) { if (PW_NULL == gc->font->bits) { IPW_ASSERT(FALSE, ("GC (%p) font bits == NULL!", gc)); return(FALSE); } if (PW_NULL == gc->font->info) { IPW_ASSERT(FALSE, ("GC (%p) font info == NULL!", gc)); return(FALSE); } }#if IPW_CHECK_EN(REGION_LIST) if (!IPw_RegionListCheck(&gc->clip_reg, TRUE)) { IPW_ASSERT(FALSE, ("GC (%p) clip region check failed!", gc)); return(FALSE); }#endif /* IPW_CHECK_EN(REGION_LIST) */ return(TRUE);}#endif /* IPW_CHECK_EN(GC_STRUCT) *//* -------------------------------------------------------------------------- *//** * Gets the width of string @p string according * to the @p font. * @param font pointer to font * @param string string * @return width of string in screen pixels */ Pw_uInt Pw_FontGetStringWidth(Pw_Font* font, Pw_Char* string){ Pw_uInt w = 0; IPW_TRACE_ENTER(DR3); IPW_CHECK_PTR2(font, string); /* Sum widths of all charachters in string */ while (*string != '\0') { w += font->info[(Pw_Byte)*string].dwx; string++; } IPW_TRACE_EXIT_V(DR3, d, w); return(w);}/** * Draws a point. * @param gc pointer to graphic context * @param x x coord * @param y y coord */void Pw_DrawPoint(Pw_GC* gc, Pw_Coord x, Pw_Coord y){ Pw_Region* reg; IPW_TRACE_ENTER(DR3); IPW_CHECK_PTR(gc); IPW_CHECK_GC(gc); IPW_TRACE2(DR3, d, x, y); /* Correct point's coords according to the graphic context origin */ x += gc->xoff; y += gc->yoff; IPW_TRACE2(DR3, d, x, y); IPW_TRACE_RECT(DR3, &gc->clip_reg.bounds); /* Check if point is inside clip region bounds */ if (!IPW_RECT_IS_POINT_IN(x, y, &gc->clip_reg.bounds)) { IPW_TRACE_EXIT(DR3); return; } /* * Check if the point is inside the clip region and draw it accordingly */ reg = gc->clip_reg.regs; while (PW_NULL != reg) { IPW_TRACE_RECT(DR3, ®->area); if (IPW_RECT_IS_POINT_IN(x, y, ®->area)) { gc->d.lld->draw_point(gc, x, y); IPW_TRACE_EXIT(DR3); return; } reg = reg->next; } IPW_TRACE_EXIT(DR3);}/** * Draws a rectangle. * @param gc pointer to graphic context * @param x x coord (of the top left corner) * @param y y coord (of the top left corner) * @param width width of rectangle * @param height height of rectangle * @see Pw_FillRect */void Pw_DrawRect(Pw_GC* gc, Pw_Coord x, Pw_Coord y, Pw_Coord w, Pw_Coord h){ Pw_Coord rx2, ry2; Pw_Rectangle r, rc; Pw_Region* reg; IPW_TRACE_ENTER(DR3); IPW_CHECK_PTR(gc); IPW_CHECK_GC(gc); IPW_TRACE4(DR3, d, x, y, w, h); /* Correct rectangle position according to graphic context origin */ r.x = x + gc->xoff; r.y = y + gc->yoff; r.w = w; r.h = h; IPW_TRACE_RECT2(DR3, &r, &gc->clip_reg.bounds); /* Check if rectangle intersects clip region bounds */ if (!IPW_RECT_IS_OVER(&r, &gc->clip_reg.bounds)) { IPW_TRACE_EXIT(DR3); return; } /* Calc rectangle bottom right corner coords */ rx2 = r.x + r.w - 1; ry2 = r.y + r.h - 1; /* * Check each rectangle in clip region - if our * rectangle intersect one of them, than draw * the visible part */ reg = gc->clip_reg.regs; while (PW_NULL != reg) { IPW_TRACE_RECT(DR3, ®->area); /* Make a copy of rectangle */ IPW_RECT_COPY(&rc, &r); /* * If rectangle intersects current * clip region rectangle than draw it */ if (IPw_RectIntersect(&rc, ®->area)) { IPW_TRACE_RECT(DR3, &rc); if (IPW_RECT_IS_EQUAL(&r, &rc)) { /* Rectangle fully visible - draw it and we are done */ gc->d.lld->draw_ver_line(gc, r.x, r.y, ry2); gc->d.lld->draw_ver_line(gc, rx2, r.y, ry2); gc->d.lld->draw_hor_line(gc, r.x, r.y, rx2); gc->d.lld->draw_hor_line(gc, r.x, ry2, rx2); IPW_TRACE_EXIT(DR3); return; } else { Pw_Coord rcx2, rcy2; /* Calc clipped rectangle bottom right corner coords */ rcx2 = rc.x + rc.w - 1; rcy2 = rc.y + rc.h - 1; /* Draw parts of rectangle that are visible */ if (r.x == rc.x) gc->d.lld->draw_ver_line(gc, rc.x, rc.y, rcy2); if (rx2 == rcx2) gc->d.lld->draw_ver_line(gc, rcx2, rc.y, rcy2); if (r.y == rc.y) gc->d.lld->draw_hor_line(gc, rc.x, rc.y, rcx2); if (ry2 == rcy2) gc->d.lld->draw_hor_line(gc, rc.x, rcy2, rcx2); } } reg = reg->next; } IPW_TRACE_EXIT(DR3);}/** * Draws a filled rectangle. * @param gc pointer to graphic context * @param x x coord (of the top left corner) * @param y y coord (of the top left corner) * @param width width of rectangle * @param height height of rectangle * @see Pw_DrawRect */void Pw_FillRect(Pw_GC* gc, Pw_Coord x, Pw_Coord y, Pw_Coord w, Pw_Coord h){ Pw_Rectangle r, rc; Pw_Region* reg; IPW_TRACE_ENTER(DR3); IPW_CHECK_PTR(gc); IPW_CHECK_GC(gc); IPW_TRACE4(DR3, d, x, y, w, h); /* Correct rectangle position according to graphic context origin */ r.x = x + gc->xoff; r.y = y + gc->yoff; r.w = w; r.h = h; IPW_TRACE_RECT2(DR3, &r, &gc->clip_reg.bounds); /* * Check if rectangle's bounding box intersects the clip region * bounding box */ if (!IPW_RECT_IS_OVER(&r, &gc->clip_reg.bounds)) { IPW_TRACE_EXIT(DR3); return; } /* * Check each rectangle in clip region - if our * rectangle intersect one of them, than draw * the visible part */ reg = gc->clip_reg.regs; while (PW_NULL != reg) { IPW_TRACE_RECT(DR3, ®->area); /* Make a copy of rectangle */ IPW_RECT_COPY(&rc, &r); /* Intersect the rectangle with current clip region rectangle */ if (IPw_RectIntersect(&rc, ®->area)) { IPW_TRACE_RECT(DR3, &rc); /* Draw the intersected rectangle */ gc->d.lld->fill_rect(gc, rc.x, rc.y, rc.w, rc.h); /* * If intersected rectangle equals the * original rectangle - we are done */ if (IPW_RECT_IS_EQUAL(&r, &rc)) { IPW_TRACE_EXIT(DR3); return; } } reg = reg->next; } IPW_TRACE_EXIT(DR3);}/** * Draws a line. * @param gc pointer to graphic context * @param x1 x coord (of start point) * @param y1 y coord (of start point) * @param x2 x coord (of end point) * @param y2 y coord (of end point) */void Pw_DrawLine(Pw_GC* gc, Pw_Coord x1, Pw_Coord y1, Pw_Coord x2, Pw_Coord y2){ Pw_Region* reg; IPW_TRACE_ENTER(DR3); IPW_CHECK_PTR(gc); IPW_CHECK_GC(gc); IPW_TRACE4(DR3, d, x1, y1, x2, y2); /* Correct the line coords according to graphic context origin */ x1 += gc->xoff; x2 += gc->xoff; y1 += gc->yoff; y2 += gc->yoff; IPW_TRACE4(DR3, d, x1, y1, x2, y2); IPW_TRACE_RECT(DR3, &gc->clip_reg.bounds); /* If line outside clip region bounds return */ if ((IPw_RectOutCode(&gc->clip_reg.bounds, x1, y1) & IPw_RectOutCode(&gc->clip_reg.bounds, x2, y2)) != 0) { IPW_TRACE_EXIT(DR3); return; } reg = gc->clip_reg.regs; /* * Check if line is an horizontal or vertical line - * if it is use faster drawing and clipping functions */ if (x1 == x2) { /* Horizontal line */ /* * Check each rectangle in clip region - if our * line intersect one of them, than draw the * visible part */ while (PW_NULL != reg) { IPW_TRACE_RECT(DR3, ®->area); if (_DrawClipVerLine(gc, x1, y1, y2, ®->area)) { IPW_TRACE_EXIT(DR3); return; } reg = reg->next; } } else if (y1 == y2) { /* Vertical line */ /* * Check each rectangle in clip region - if our * line intersect one of them, than draw the * visible part */ while (PW_NULL != reg) { IPW_TRACE_RECT(DR3, ®->area); if (_DrawClipHorLine(gc, x1, y1, x2, ®->area))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -